Joining based on Sum of amount - oracle
Basically there are 2 files
File 1 sample
Reference
Amount
AA1
1000
File 2 sample
Reference
Match_No
Side
Amount
AA1
123
Ledger
1000
BB1
123
Statement
500
CC1
123
Statement
500
Now the requirement is using the reference from File 1 extract the Match_No from file 2 where side = 'Ledger'
The script I think for this should be:-
select file2.match_no
from file1 join file2 on file1.reference = file2.reference
where side = 'Ledger'
Now after extracting Match_No where side = Ledger, for the same Match_No extract all the references from file 2 where side ='Statement' and sum of file2.amounts (where side='Statement') = file2.amount(where side = Ledger)
This is how I understood what you are saying. See if it helps.
SQL> with
2 -- Sample data; you have it already & don't type it
3 file_1 (reference, amount) as
4 (select 'aa1', 1000 from dual),
5 file_2 (reference, match_no, side, amount) as
6 (select 'aa1', 123, 'Ledger' , 1000 from dual union all
7 select 'bb1', 123, 'Statement', 500 from dual union all
8 select 'cc1', 123, 'Statement', 500 from dual
9 ),
10 -- Useful code begins here.
11 -- Query you posted (I added "B.AMOUNT" and used it in line #21)
12 qyp as
13 (select b.match_no, b.amount
14 from file_1 a join file_2 b on a.reference = b.reference
15 where b.side = 'Ledger'
16 )
17 -- The final query
18 select b.reference
19 from file_2 b join qyp q on q.match_no = b.match_no
20 where b.side = 'Statement'
21 and q.amount = (select sum(c.amount)
22 from file_2 c
23 where c.match_no = b.match_no
24 and c.side = 'Statement'
25 );
REF
---
cc1
bb1
SQL>
Related
Oracle Subquery while using count and max with join
Table COMPUTER: Table SUPPLIER: how to display the building location that has the most computers? i Have been trying several ways include subquery, joins, max, count but all not working and error keeps happending The result i pursueing is SUPPID SNAME SADDRESS MAKE COUNT(*) 125 Apple Sdn.Bhd 18 Jalan Duta Apple 3
For example (where sample data is in lines #1 - 12; query you might be interested in begins at line #13): SQL> with 2 -- sample data 3 computer (compid, make, suppid, locid) as 4 (select 13323, 'IBM' , 124, 333 from dual union all 5 select 13324, 'Apple', 125, 444 from dual union all 6 select 13325, 'Apple', 125, 444 from dual union all 7 select 13326, 'Apple', 125, 444 from dual 8 ), 9 supplier (suppid, sname, saddress) as 10 (select 124, 'IBM Sdn.Bhd' , '15 Jalan Duta' from dual union all 11 select 125, 'Apple Sdn.Bhd', '18 Jalan Duta' from dual 12 ), 13 comp_loc as 14 -- number of computers per location; RNK = 1 shows location with most computers 15 (select locid, 16 rank() over (order by count(*) desc) rnk, 17 count(*) cnt 18 from computer 19 group by locid 20 ) 21 select distinct s.suppid, s.sname, s.saddress, c.make, l.cnt 22 from supplier s join computer c on c.suppid = s.suppid 23 join comp_loc l on l.locid = c.locid 24 where l.rnk = 1; SUPPID SNAME SADDRESS MAKE CNT ---------- ------------- ------------- ----- ---------- 125 Apple Sdn.Bhd 18 Jalan Duta Apple 3 SQL>
On Oracle 12 and newer select s.suppid, s.sname, s.saddress, c.make, count(1) from COMPUTER c join SUPPLIER s on c.suppid = s.suppid group by s.suppid, s.sname, s.saddress, c.make order by count(1) desc fetch first 1 row only <-- this line will fetch you the top 1 line only You might also use "fetch first 1 row with ties" to output all the top manufacturers if there are many of them having same "count". E.g If IBM and Appl were having same amount of lines On Oracle version before 12 do the following: select * from (select s.suppid, s.sname, s.saddress, c.make, count(1) from comps c join suppls s on c.suppid = s.suppid group by s.suppid, s.sname, s.saddress, c.make order by count(1) desc) where rownum = 1; <-- this line will get you the top 1 manufacturer only PS. version of the oracle database can be obtained for example using: select version from v$instance;
search in text using subtext in Oracle PLSQL
I have this query in master_t table that hold ration_category column and many number of sectors in sectors column like this 'BN:INS' or 'BN' or 'BN:IM:INS' etc.. select distinct ratio_category d from master_t where status = 'Y' and (SECTORS = :P23_SECTORS or (INSTR(':'||:SECTORS ||':',:P23_SECTORS)>0 OR UPPER(:P23_SECTORS) = 'ALL')) order by ratio_category P23_SECTORS= 'BN:INS' SECTORS='INS:MFI:SB:BN' : is a separator of multi data I need to check if data inside P23_sectors are exists in SECTORS variable , but this query doesn't get data because the multi data separator Is there anyway to adjust the query so I could compare subtext with full text note : the order is different. Expected output : LL PP CC Thanks
Here's one option (read comments within code): SQL> with master_t (ratio_category, sectors) as 2 -- sample data 3 (select 1, 'INS:MFI:SB:BN' from dual union all 4 select 2, 'BN:LF' from dual 5 ), 6 split_t as 7 -- split SECTORS into rows 8 (select ratio_category, 9 sectors, 10 regexp_substr(sectors, '[^:]+', 1, column_value) sec 11 from master_t cross join 12 table(cast(multiset(select level from dual 13 connect by level <= regexp_count(sectors, ':') + 1 14 ) as sys.odcinumberlist)) 15 ), 16 split_23 as 17 -- split P23_SECTORS into rows 18 (select regexp_substr('&&P23_SECTORS', '[^:]+', 1, level) sec, 19 regexp_count('&&P23_SECTORS', ':') + 1 cnt 20 from dual 21 connect by level <= regexp_count('&&P23_SECTORS', ':') + 1 22 ) 23 -- return rows that contain complete P23_SECTORS value(s) 24 select t.ratio_category, t.sectors 25 from split_t t join split_23 s on s.sec = t.sec 26 group by t.ratio_category, t.sectors 27 having count(*) = max(s.cnt); Enter value for p23_sectors: BN:INS RATIO_CATEGORY SECTORS -------------- ------------- 1 INS:MFI:SB:BN SQL> Pay attention to comments people posted. They do have serious experience with programming and you'd rather listen to what they say and thank them for spending time to check your problem. Your reply to Ed is rather rude; if I were Ed, I'd make sure not to respond to any of your future questions (read: I'd let you solve your own problems).
How to find text fields that contains a list of words
I'm using Oracle PLSQL. I want to return TextFields that contains a list of words (with 'and' operator between them). The result string must contain all the words provided from the user, the order is not importent. Example: param_col varchar2(100):= 'Project|Data|Book'; (The list of words are unknown, depend on user parameter) TextField: 1.'The Project will contain Data from Book' 2.'The Project Data is not valid. 3.'Project is the best data Book exists' Expected Result: 1.'The Project will contain Data from Book' 3.'Project is the best data Book exists'
Here's one option. See comments within code. SQL> with 2 test (id, col) as 3 -- Test sample data 4 (select 1, 'The Project will contain Data from Book' from dual union all 5 select 2, 'The Project Data is not valid' from dual union all 6 select 3, 'Project is the best data Book exists' from dual 7 ), 8 param (par) as 9 -- input parameter 10 (select 'Project|Data|Book' from dual), 11 -- 12 spltest as 13 -- split TEST sentences to words 14 (select id, 15 lower(regexp_substr(col, '[^ ]+', 1, column_value)) val 16 from test cross join table(cast(multiset(select level from dual 17 connect by level <= regexp_count(col, ' ') + 1 18 ) as sys.odcinumberlist)) 19 ), 20 splpar as 21 -- split PARAMETER into words; include IDs from TEST 22 (select t.id, 23 lower(regexp_substr(p.par, '[^\|]+', 1, column_value)) val 24 from param p cross join test t 25 cross join table(cast(multiset(select level from dual 26 connect by level <= regexp_count(p.par, '\|') + 1 27 ) as sys.odcinumberlist)) 28 ) 29 -- final result: select rows from the TEST table ... 30 select t.id, t.col 31 from test t 32 -- ... where ID is contained in intersected set of values from SPLTEST and SPLPAR ... 33 where t.id in (select x.id from (select t1.id, t1.val from spltest t1 34 intersect 35 select p.id, p.val from splpar p 36 ) x 37 group by x.id 38 -- ... while that "intersected set" has to contain all values from the PARAM 39 having count(*) = (select regexp_count(p1.par, '\|') + 1 40 from param p1 41 ) 42 ); ID COL ---------- --------------------------------------- 1 The Project will contain Data from Book 3 Project is the best data Book exists SQL>
How to return non-empty rows for a given ID - Hive
I have a table X ID A B -------------- 1 abc 27 1 - 28 2 - 33 3 xyz 41 3 - 07 I need output as ID A B -------------- 1 abc 27 2 - 33 3 xyz 41 I tried doing max(A) OVER (PARTITION BY ID) as the_value but it did not work. I can still see all the rows in the output table. I was wondering if somebody has come across a similar situation and has a solution to this ?
you can use this simple trick for getting the full record for which some column is maxed: select original.* from (select ID,max(B) as B from Tbl group by ID ) maxB inner join (select * from Tbl ) original on original.ID = maxB.ID and original.B = maxB.B now this is of course an overkill code. you can also do: select Tbl.* from (select ID,max(B) as B from Tbl group by ID ) maxB inner join Tbl on Tbl.ID = maxB.ID and Tbl.B = maxB.B but the first version is more of a template to do whatever you want with further columns, fields, conditions joins etc.
Max size in a connected by prior Oracle
I've got some help turning my table of the sort: Col 23 25 15 53 ... into something like 23,25,15,53... The query that does it is SELECT max(ltrim(sys_connect_by_path(flow_run_id, ','), ',')) FROM (select flow_run_id, rownum rn from table where CREATED_DATE < sysdate - 32 and flow_id = 3 order by 1 desc) START WITH rn = 1 CONNECT BY PRIOR rn = rn - 1 (this beaulty was given by Michael in here) My current problem is that the result is too long (ORA-01489 over the 4k chars from varchar2). I'm still learning about these sys_connected_by_path so I'd need some help sorting this. How could I make this query return me multiple rows instead of one super long line? i.e.: Instead of 419,1,2,3,411,418,4,415,887,413,414,201,888,890,401,417,610,412,416,5,6,922,1080,1422,1423,1411,1412,1413,1414,1415,1416,1417,1418,1419,1964,2217,1636,2037,1988,1970,2038,1989,2000,2040,1993,2043,1994,2001,2044,1658,1995,2045,2224,1996,2019,1678,1997,2022,2201,1680,2219,2024,2207,1677,2209,2220,1959,2211,1961,2026,2212,1962,2028,2215,1675,1676,2035,2216,1986,1963,2017,1983,1935,2002,2018,1985,1936,2003,2020,2032,1937,2004,2021,2033,1938,1943,2023,2034,1939,1944,2025,2225,1941,1950,2027,2036,1942,1955,2029,2041,1945,1956,2030,2227,1946,1957,2031,2039,1947,2005,1974,2042,1948,2006,1976,2228,1949,2007,1978,1951,2009,1979,1929,1952,2012,1980,1931,1953,2013,1981,1933,1954,2015,2334,2350,2311,2239,2240,2241,2242,2245,2246,2249,2250,2336,2312,2008,2010,2011,2014,2251,2253,2016,2243,2244,2247,2351,2248,(...) get 419,1,2,3,411,418,4,415,887,413,414,201,888,890,401,417,610,412,416,5,6,922,1080 1423,1411,1412,1413,1414,1415,1416,1417,1418,1419,1964,2217,1636,2037,1988,1970,2038 2000,2040,1993,2043,1994,2001,2044,1658,1995,2045,2224,1996,2019,1678,1997,2022,2201 (...) Any tips? Thanks! f.
the following query will cut your big string in parts: SQL> SELECT root_rn, MAX(concat) 2 FROM (SELECT connect_by_root(rn) root_rn, 3 ltrim(sys_connect_by_path(flow_run_id, ','), ',') concat 4 FROM (SELECT flow_run_id, rownum rn 5 FROM (SELECT round(dbms_random.VALUE(1, 10000)) 6 AS flow_run_id 7 FROM dual 8 CONNECT BY ROWNUM <= 2000) 9 ORDER BY 1 DESC) 10 START WITH MOD(rn, 10) = 1 11 CONNECT BY PRIOR rn = rn - 1 12 AND MOD(rn, 10) != 1) 13 GROUP BY root_rn 14 ORDER BY root_rn; ROOT_RN MAX(CONCAT) ---------- ------------------------------------------------------------------- 1 654,6710,5297,5481,5085,2793,7646,9170,1051,2387 11 1882,8285,5430,4928,267,3779,3843,1151,3085,1446 21 4721,6087,6755,9904,805,2776,4633,2772,7785,5818 31 5189,5307,6481,2099,3832,9788,5970,8068,6605,3904 41 53,7013,1314,7717,9320,7069,907,5367,5013,7637 51 3903,2318,2611,7954,5751,5598,6148,6555,9724,984 [...] You can replace "10" with a bigger number if you want more elements on each row.
Some little modifications to keep order SELECT 10*frn+1 root,ltrim(sys_connect_by_path(flow_run_id,','),',') FROM (SELECT flow_run_id,mod(rn,10) mrn,floor(rn/10) frn,count(*)over(partition by floor(rn/10))-1 crn FROM (SELECT flow_run_id, row_number()over(order by flow_run_id)-1 rn FROM (SELECT round(dbms_random.VALUE(1, 10000)) AS flow_run_id FROM dual CONNECT BY ROWNUM <= 2000 ) ) ) WHERE crn = mrn START WITH mrn = 0 CONNECT BY PRIOR mrn = mrn-1 AND PRIOR frn = frn