how to join 2 tables in SQL oracle - sql

please help me, I want to join from skyteam1 (ID 1, comno 1, ename Boeing737, country USA)
into comm1 (id 1, comno (all), ename (all), ddate(all), SUM (total price) of the aircraft
SQL> SELECT * FROM SKYTEAM1;
ID; COMNO; ENAME; COUNTRY;
1 1 Boeing737 USA
2 2 Boeing777 USA
3 3 AirBus320 RUSSIA
SQL> SELECT * FROM COMM1;
ID; COMNO; ENAME; DDATE; SAL; DEPTNO;
1 1 Engine 20.02.81 900 20
1 2 Wings 22.02.81 35000 30
1 3 Battery 09.06.81 84800 20
1 4 APU 17.11.81 8400 10
1 5 EECU 03.12.81 8400 20
1 6 Generator 23.01.82 40000 20
EXAMPLE;
I need this ANSWER
ID; COMNO; ENAME; ENAME; DDATE; SAL; SUM_TOTAL;
1 1 Boeing737 Engine 20.02.81 900
2 Wings 22.02.81 35000
3 Battery 09.06.81 84800
4 APU 17.11.81 8400
5 EECU 03.12.81 8400
6 Generator 23.01.82 40000 17750;

Here's an example:
SQL> with skyteam1 (id, comno, ename) as
2 (select 1, 1, 'boeing 737' from dual union all
3 select 2, 2, 'boeing 777' from dual union all
4 select 3, 3, 'airbus 320' from dual
5 ),
6 comm1 (id, comno, ename, ddate, sal) as
7 (select 1, 1, 'engine', '20.02.81', 900 from dual union all
8 select 1, 2, 'wings', '22.02.81', 35000 from dual union all
9 select 1, 3, 'battery', '09.06.81', 84800 from dual union all
10 select 1, 4, 'apu', '17.11.81', 8400 from dual union all
11 select 1, 5, 'eecu', '03.12.81', 8400 from dual union all
12 select 1, 6, 'generator', '23.01.81', 40000 from dual
13 )
14 select c.id,
15 c.comno,
16 s.ename,
17 c.ename,
18 c.ddate,
19 c.sal,
20 sum(c.sal) over (order by null) total
21 from skyteam1 s join comm1 c on c.id = s.id
22 where s.id = 1
23 order by c.comno;
ID COMNO ENAME ENAME DDATE SAL TOTAL
---------- ---------- ---------- --------- -------- ---------- ----------
1 1 boeing 737 engine 20.02.81 900 177500
1 2 boeing 737 wings 22.02.81 35000 177500
1 3 boeing 737 battery 09.06.81 84800 177500
1 4 boeing 737 apu 17.11.81 8400 177500
1 5 boeing 737 eecu 03.12.81 8400 177500
1 6 boeing 737 generator 23.01.81 40000 177500
6 rows selected.
SQL>
Depending on a tool you use, it can be made prettier. For example, in SQL*Plus:
SQL> break on id on s_ename
SQL> compute sum of sal on id
SQL>
SQL> with skyteam1 (id, comno, ename) as
2 (select 1, 1, 'boeing 737' from dual union all
3 select 2, 2, 'boeing 777' from dual union all
4 select 3, 3, 'airbus 320' from dual
5 ),
6 comm1 (id, comno, ename, ddate, sal) as
7 (select 1, 1, 'engine', '20.02.81', 900 from dual union all
8 select 1, 2, 'wings', '22.02.81', 35000 from dual union all
9 select 1, 3, 'battery', '09.06.81', 84800 from dual union all
10 select 1, 4, 'apu', '17.11.81', 8400 from dual union all
11 select 1, 5, 'eecu', '03.12.81', 8400 from dual union all
12 select 1, 6, 'generator', '23.01.81', 40000 from dual
13 )
14 select c.id,
15 c.comno,
16 s.ename s_ename,
17 c.ename c_ename,
18 c.ddate,
19 c.sal
20 from skyteam1 s join comm1 c on c.id = s.id
21 where s.id = 1
22 order by c.comno;
ID COMNO S_ENAME C_ENAME DDATE SAL
---------- ---------- ---------- --------- -------- ----------
1 1 boeing 737 engine 20.02.81 900
2 wings 22.02.81 35000
3 battery 09.06.81 84800
4 apu 17.11.81 8400
5 eecu 03.12.81 8400
6 generator 23.01.81 40000
********** ********** ----------
sum 177500
6 rows selected.
SQL>

Related

How to find the row with the highest value cell based on another column from within a group of values?

I have this table:
Site_ID
Volume
RPT_Date
RPT_Hour
1
10
01/01/2021
1
1
7
01/01/2021
2
1
13
01/01/2021
3
1
11
01/16/2021
1
1
3
01/16/2021
2
1
5
01/16/2021
3
2
9
01/01/2021
1
2
24
01/01/2021
2
2
16
01/01/2021
3
2
18
01/16/2021
1
2
7
01/16/2021
2
2
1
01/16/2021
3
I need to select the RPT_Hour with the highest Volume for each set of dates
Needed Output:
Site_ID
Volume
RPT_Date
RPT_Hour
1
13
01/01/2021
1
1
11
01/16/2021
1
2
24
01/01/2021
2
2
18
01/16/2021
1
SELECT site_id, volume, rpt_date, rpt_hour
FROM (SELECT t.*,
ROW_NUMBER()
OVER (PARTITION BY site_id, rpt_date ORDER BY volume DESC) AS rn
FROM MyTable) t
WHERE rn = 1;
I cannot figure out how to group the table into like date groups. If I could do that, I think the rn = 1 will return the highest volume row for each date.
The way I see it, your query is OK (but rpt_hour in desired output is not).
SQL> with test (site_id, volume, rpt_date, rpt_hour) as
2 (select 1, 10, date '2021-01-01', 1 from dual union all
3 select 1, 7, date '2021-01-01', 2 from dual union all
4 select 1, 13, date '2021-01-01', 3 from dual union all
5 select 1, 11, date '2021-01-16', 1 from dual union all
6 select 1, 3, date '2021-01-16', 2 from dual union all
7 select 1, 5, date '2021-01-16', 3 from dual union all
8 --
9 select 2, 9, date '2021-01-01', 1 from dual union all
10 select 2, 24, date '2021-01-01', 3 from dual union all
11 select 2, 16, date '2021-01-01', 3 from dual union all
12 select 2, 18, date '2021-01-16', 1 from dual union all
13 select 2, 7, date '2021-01-16', 2 from dual union all
14 select 2, 1, date '2021-01-16', 3 from dual
15 ),
16 temp as
17 (select t.*,
18 row_number() over (partition by site_id, rpt_date order by volume desc) rn
19 from test t
20 )
21 select site_id, volume, rpt_date, rpt_hour
22 from temp
23 where rn = 1
24 /
SITE_ID VOLUME RPT_DATE RPT_HOUR
---------- ---------- ---------- ----------
1 13 01/01/2021 3
1 11 01/16/2021 1
2 24 01/01/2021 3
2 18 01/16/2021 1
SQL>
One option would be using MAX(..) KEEP (DENSE_RANK ..) OVER (PARTITION BY ..) analytic function without need of any subquery such as :
SELECT DISTINCT
site_id,
MAX(volume) KEEP (DENSE_RANK FIRST ORDER BY volume DESC) OVER
(PARTITION BY site_id, rpt_date) AS volume,
rpt_date,
MAX(rpt_hour) KEEP (DENSE_RANK FIRST ORDER BY volume DESC) OVER
(PARTITION BY site_id, rpt_date) AS rpt_hour
FROM t
GROUP BY site_id, rpt_date, volume, rpt_hour
ORDER BY site_id, rpt_date
Demo

list of months error

I have a table defined as follows
create table test (
m_year varchar2(10),
val number
);
data looks like
myear val
Jan 10 876
Sep 10 709
Jan 11 46
Apr 11 99
Jan 12 878
I want to get output as
01-Jan-10 876
01-Feb-10 876
'
'
'
01-Sep-10 709
'
'
'
sysdate 878
My query looks like
select to_char(add_months(myear,level-1)) months,val
from (
select val, to_date(myear,'mm-yyyy') myear,
lead(to_date(myear,'mm-yyyy'),1,sysdate) over (order by to_date(myear,'mm-yyyy')) as nxt
from test
)
connect by level <= months_between(nxt,myear)+1;
Few months are being missed and I'm getting an infinite loop in the output
Here's one option:
SQL> create table test
2 (m_year varchar2(10),
3 val number);
Table created.
SQL> insert into test
2 select 'Jan 10', 876 from dual union
3 select 'Sep 10', 709 from dual union
4 select 'Jan 11', 46 from dual union
5 select 'Apr 11', 99 from dual union
6 select 'Jan 12', 878 from dual;
5 rows created.
Query:
SQL> with
2 dates as
3 (select to_date(m_year, 'mon rr', 'nls_date_language = english') m_year,
4 val
5 from test
6 ),
7 whole_period as
8 (select add_months(min_year, level - 1) m_year
9 from (select min(m_year) min_year,
10 trunc(sysdate, 'mm') max_year
11 from dates
12 )
13 connect by level <= months_between(max_year, min_year) + 1
14 )
15 select
16 w.m_year,
17 last_value(d.val) ignore nulls over
18 (order by w.m_year rows between unbounded preceding and current row) val
19 from whole_period w left join dates d on d.m_year = w.m_year
20 order by w.m_year;
M_YEAR VAL
---------- ----------
01.01.2010 876
01.02.2010 876
01.03.2010 876
01.04.2010 876
01.05.2010 876
01.06.2010 876
01.07.2010 876
01.08.2010 876
01.09.2010 709
01.10.2010 709
01.11.2010 709
01.12.2010 709
01.01.2011 46
01.02.2011 46
01.03.2011 46
01.04.2011 99
01.05.2011 99
01.06.2011 99
01.07.2011 99
01.08.2011 99
01.09.2011 99
01.10.2011 99
01.11.2011 99
01.12.2011 99
01.01.2012 878
01.02.2012 878
01.03.2012 878
<snip>
01.03.2018 878
01.04.2018 878
01.05.2018 878
101 rows selected.
SQL>
The lazy way of doing the same - easy to read, easy to maintain. The distinct may slow down the performance.
And next time please add your test data and structures to your posts. You will get answers faster.
SELECT DISTINCT add_months(start_date, LEVEL-1) final_date
, start_date
, end_month
FROM
(
SELECT to_date(myear) start_date
, LAG(to_date(myear)) OVER (ORDER BY myear DESC) end_date
, MIN(EXTRACT(MONTH FROM myear)) OVER (ORDER BY myear) start_month
, MAX(EXTRACT(MONTH FROM myear)) OVER (ORDER BY myear DESC) end_month
, ROW_NUMBER() OVER (PARTITION BY EXTRACT(YEAR FROM myear)
ORDER BY EXTRACT(YEAR FROM myear)) rno
FROM
(
SELECT to_date('01-2010', 'mm-yyyy') myear FROM dual
UNION ALL
SELECT to_date('09-2010', 'mm-yyyy') FROM dual
UNION ALL
SELECT to_date('01-2011', 'mm-yyyy') FROM dual
UNION ALL
SELECT to_date('04-2011', 'mm-yyyy') FROM dual
)
)
WHERE rno = 1
CONNECT BY LEVEL <= end_month
ORDER BY start_date
/
FINAL DATE START DATE END MONTH
----------------------------------
01-JAN-10 01-JAN-10 9
01-FEB-10 01-JAN-10 9
01-MAR-10 01-JAN-10 9
01-APR-10 01-JAN-10 9
01-MAY-10 01-JAN-10 9
01-JUN-10 01-JAN-10 9
01-JUL-10 01-JAN-10 9
01-AUG-10 01-JAN-10 9
01-SEP-10 01-JAN-10 9
01-JAN-11 01-JAN-11 4
01-FEB-11 01-JAN-11 4
01-MAR-11 01-JAN-11 4
01-APR-11 01-JAN-11 4

SQL - Selecting the rows with max timestamp by group

I have this table
SITE S_ID BAN COUNT P V TIMESTAMP
23 1 4 1500 0,05 50 10/05/17 09:58:22,609000000
23 3 3 800 0,05 50 10/05/17 09:58:22,736000000
23 2 3 3000 0,05 50 10/05/17 09:58:22,674000000
23 1 4 1500 0,05 50 10/05/17 15:57:04,079000000
23 1 4 1499 0,05 50 10/05/17 15:53:38,851000000
20 1 3 2000 0,1 50 10/05/17 10:57:07,172000000
20 2 3 2000 0,1 50 10/05/17 10:59:50,127000000
20 3 2 3000 0,1 50 10/05/17 11:00:39,051000000
20 4 2 3000 0,1 50 10/05/17 11:01:15,533000000
and I'm trying to obtain something like this:
SITE S_ID BAN COUNT P V TIMESTAMP
23 3 3 800 0,05 50 10/05/17 09:58:22,736000000
23 2 3 3000 0,05 50 10/05/17 09:58:22,674000000
23 1 4 1500 0,05 50 10/05/17 15:57:04,079000000
20 1 3 2000 0,1 50 10/05/17 10:57:07,172000000
20 2 3 2000 0,1 50 10/05/17 10:59:50,127000000
20 3 2 3000 0,1 50 10/05/17 11:00:39,051000000
20 4 2 3000 0,1 50 10/05/17 11:01:15,533000000
i.e. for every SITE the S_ID, BAN, COUNT, P, V and TIMESTAMP with the MAX(TIMESTAMP)
Here you go:
SELECT
SITE
, S_ID
,BAN
,COUNT
,P
,V
,TimeStamp
FROM [Your Table Name]
INNER JOIN
(
SELECT
SITE
, S_ID
, MAX(TIMESTAMP) as MaxTimeStamp
FROM [Your Table Name]
GROUP BY
SITE
, S_ID
) AS MaxDAata ON
MaxData.SITE = [Your Table Name].SITE
AND MaxData.S_ID = [Your Table Name].S_ID
AND MaxData.TimeStamp = [Your Table Name].MaxTimeStamp
I would make use of an analytic function to rank the dates within a group (partition) then only return the top ranked items. I'm not sure your partition so I used the fields site, s_id, ban
select * from
(with test_data (SITE, S_ID, BAN, s_COUNT, P, V, s_TIMESTAMP) as (
select 23, 1, 4, 1500, 0.05, 50, to_timestamp('10/05/17 09:58:22,609','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 23, 3, 3, 800 , 0.05, 50, to_timestamp('10/05/17 09:58:22,736','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 23, 2, 3, 3000, 0.05, 50, to_timestamp('10/05/17 09:58:22,674','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 23, 1, 4, 1500, 0.05, 50, to_timestamp('10/05/17 15:57:04,079','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 23, 1, 4, 1499, 0.05, 50, to_timestamp('10/05/17 15:53:38,851','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 20, 1, 3, 2000, 0.1 , 50, to_timestamp('10/05/17 10:57:07,172','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 20, 2, 3, 2000, 0.1 , 50, to_timestamp('10/05/17 10:59:50,127','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 20, 3, 2, 3000, 0.1 , 50, to_timestamp('10/05/17 11:00:39,051','MM/DD/YY HH24:MI:SS,FF') from dual union all
select 20, 4, 2, 3000, 0.1 , 50, to_timestamp('10/05/17 11:01:15,533','MM/DD/YY HH24:MI:SS,FF') from dual
)
SELECT site, s_id, ban, s_count, p, v, s_timestamp,
rank() over (partition by site, s_id, ban order by s_timestamp desc) as r
FROM test_data
)
where r = 1
order by site, s_id
SITE|S_ID|BAN|S_COUNT|P|V|S_TIMESTAMP|R
20|1|3|2000|0.1|50|05-OCT-17 10.57.07.172000000 AM|1
20|2|3|2000|0.1|50|05-OCT-17 10.59.50.127000000 AM|1
20|3|2|3000|0.1|50|05-OCT-17 11.00.39.051000000 AM|1
20|4|2|3000|0.1|50|05-OCT-17 11.01.15.533000000 AM|1
23|1|4|1500|0.05|50|05-OCT-17 03.57.04.079000000 PM|1
23|2|3|3000|0.05|50|05-OCT-17 09.58.22.674000000 AM|1
23|3|3|800|0.05|50|05-OCT-17 09.58.22.736000000 AM|1

Oracle - Return products that have been ordered regularly

I have having trouble coding an expression which will display products where there has been no more than a one year gap in between orders. Therefore I can classify these as regular orders. To clarify I DO NOT want to return a product that has been ordered more than once in one year.
These are my two tables:
SALES FACT TABLE
TIME_KEY PRODUCT_KEY BRANCH_KEY LOCATION_KEY POUNDS_SOLD AVG_SALES UNITS_SOLD
----------------------------- ----------- ---------- ------------ ----------- ---------- ----------
22-DEC-13 08.31.18.442000000 2 B1 L19 21542.39 10821.2 100
21-DEC-10 21.19.37.182000000 3 B8 L5 65487 32793.5 100
13-SEP-13 06.36.03.720000000 7 B2 L15 78541.84 39470.92 400
24-JUN-13 12.21.45.186000000 1 B7 L13 94115 47167.5 220
18-SEP-07 12.58.06.873000000 8 B2 L2 54000 27250 500
11-FEB-11 18.06.08.475000000 8 B9 L6 11123 5636.5 150
28-SEP-13 15.06.20.153000000 6 B3 L16 45896.31 23008.16 120
22-DEC-08 19.34.48.490000000 5 B6 L3 87451.01 43875.51 300
23-JUL-13 20.08.51.173000000 6 B6 L14 69542 34971 400
20-DEC-13 22.47.24.962000000 9 B4 L17 21584.39 10872.2 160
21-DEC-06 19.11.50.472000000 5 B10 L1 10000 27250 500
13-MAR-13 14.13.58.555000000 1 B2 L11 62413 31256 99
06-MAR-13 18.15.40.365000000 4 B6 L10 94785 47542.5 300
20-DEC-13 23.35.12.683000000 2 B5 L18 52359.19 26289.6 220
15-MAR-13 19.11.58.459000000 4 B9 L12 66499.84 33299.92 100
19-DEC-11 13.17.34.443000000 9 B2 L7 51449 26049.5 650
14-FEB-12 10.20.20.787000000 10 B5 L8 66589 33394.5 200
19-DEC-09 10.09.41.844000000 3 B7 L4 99125 49687.5 250
22-MAR-12 19.36.24.790000000 10 B2 L9 62331.66 31765.83 1200
11-JAN-14 19.18.58.595000000 7 B8 L20 35214.85 17667.43 120
PRODUCT DIMENSION TABLE
PRODUCT_KEY PRODUCT_NAME BRAND TYPE SUPPLIER_TYPE
----------- ------------------------- -------------------- ---------- ----------------
1 SVF1521P2EB SONY LAPTOP WHOLESALER
2 15-A003SA COMPAQ LAPTOP WHOLESALER
3 15-N271SA HP LAPTOP RETAIL
4 15-N290SA HP LAPTOP RETAIL
5 E6400 DELL LAPTOP RETAIL
6 SVF1521C2EB SONY LAPTOP WHOLESALER
7 SVF1532K4EB SONY LAPTOP WHOLESALER
8 C50-A-1CK TOSHIBA LAPTOP WHOLESALER
9 NX.MF8EK.001 ACER LAPTOP RETAIL
10 NP915S3G-K01UK SAMSUNG LAPTOP RETAIL
I am assuming to achieve the desired output I would need to compare the date etc but am struggling.
Does this help You?
select * from (
select
--row_number() over ( partition by product_key order by time_key ) as rn
--,lead(time_key) over ( partition by product_key order by time_key ) as l
lead(time_key) over ( partition by product_key order by time_key ) - time_key as diff
,a.*
from
(
select sysdate as TIME_KEY, 0 as PRODUCT_KEY, 'XX' as BRANCH_KEY, 'XX' as LOCATION_KEY, 0 as POUNDS_SOLD, 0 as AVG_SALES, 0 as UNITS_SOLD from dual union all
select to_date('22-DEC-13 08.31.18','DD-MON-YY HH24.MI.SS'), 2, 'B1', 'L19', 21542.39, 10821.2, 100 from dual union all
select to_date('21-DEC-10 21.19.37','DD-MON-YY HH24.MI.SS'), 3, 'B8', 'L5 ', 65487, 32793.5, 100 from dual union all
select to_date('13-SEP-13 06.36.03','DD-MON-YY HH24.MI.SS'), 7, 'B2', 'L15', 78541.84, 39470.92, 400 from dual union all
select to_date('24-JUN-13 12.21.45','DD-MON-YY HH24.MI.SS'), 1, 'B7', 'L13', 94115, 47167.5, 220 from dual union all
select to_date('18-SEP-07 12.58.06','DD-MON-YY HH24.MI.SS'), 8, 'B2', 'L2 ', 54000, 27250, 500 from dual union all
select to_date('11-FEB-11 18.06.08','DD-MON-YY HH24.MI.SS'), 8, 'B9', 'L6 ', 11123, 5636.5, 150 from dual union all
select to_date('28-SEP-13 15.06.20','DD-MON-YY HH24.MI.SS'), 6, 'B3', 'L16', 45896.31, 23008.16, 120 from dual union all
select to_date('22-DEC-08 19.34.48','DD-MON-YY HH24.MI.SS'), 5, 'B6', 'L3 ', 87451.01, 43875.51, 300 from dual union all
select to_date('23-JUL-13 20.08.51','DD-MON-YY HH24.MI.SS'), 6, 'B6', 'L14', 69542, 34971, 400 from dual union all
select to_date('20-DEC-13 22.47.24','DD-MON-YY HH24.MI.SS'), 9, 'B4', 'L17', 21584.39, 10872.2, 160 from dual union all
select to_date('21-DEC-06 19.11.50','DD-MON-YY HH24.MI.SS'), 5, 'B10', 'L1 ', 10000, 27250, 500 from dual union all
select to_date('13-MAR-13 14.13.58','DD-MON-YY HH24.MI.SS'), 1, 'B2', 'L11', 62413, 31256, 99 from dual union all
select to_date('06-MAR-13 18.15.40','DD-MON-YY HH24.MI.SS'), 4, 'B6', 'L10', 94785, 47542.5, 300 from dual union all
select to_date('20-DEC-13 23.35.12','DD-MON-YY HH24.MI.SS'), 2, 'B5', 'L18', 52359.19, 26289.6, 220 from dual union all
select to_date('15-MAR-13 19.11.58','DD-MON-YY HH24.MI.SS'), 4, 'B9', 'L12', 66499.84, 33299.92, 100 from dual union all
select to_date('19-DEC-11 13.17.34','DD-MON-YY HH24.MI.SS'), 9, 'B2', 'L7 ', 51449, 26049.5, 650 from dual union all
select to_date('14-FEB-12 10.20.20','DD-MON-YY HH24.MI.SS'), 10, 'B5', 'L8 ', 66589, 33394.5, 200 from dual union all
select to_date('19-DEC-09 10.09.41','DD-MON-YY HH24.MI.SS'), 3, 'B7', 'L4 ', 99125, 49687.5, 250 from dual union all
select to_date('22-MAR-12 19.36.24','DD-MON-YY HH24.MI.SS'), 10, 'B2', 'L9 ', 62331.66, 31765.83, 1200 from dual union all
select to_date('11-JAN-14 19.18.58','DD-MON-YY HH24.MI.SS'), 7, 'B8', 'L20', 35214.85, 17667.43, 120 from dual
) a ) where diff >= 365;

Finding dates when accounts reach zero

Thanks for taking the time to examine my issue.
I'm trying to figure out a way to return dates when an account reaches 0
Sample data:
DATE ACCOUNT AMOUNT
11/01 001 100
11/02 002 50
11/03 001 -100
11/07 001 20
11/15 002 -50
11/20 001 -20
Wanted results:
Account ZeroDate
001 11/03
002 11/15
001 11/20
So far I haven't been able to figure out anything that works. Might you be able to point me in the right direction?
Thanks again in advance!
You can use analytic functions to compute the running balance
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select date '2011-11-01' dt, 1 account, 100 amt from dual union all
3 select date '2011-11-02', 2, 50 from dual union all
4 select date '2011-11-03', 1, -100 from dual union all
5 select date '2011-11-07', 1, 20 from dual union all
6 select date '2011-11-15', 2, -50 from dual union all
7 select date '2011-11-20', 1, -20 from dual
8 )
9 select dt,
10 account,
11 amt,
12 sum(amt) over (partition by account order by dt) current_balance
13* from x
SQL> /
DT ACCOUNT AMT CURRENT_BALANCE
--------- ---------- ---------- ---------------
01-NOV-11 1 100 100
03-NOV-11 1 -100 0
07-NOV-11 1 20 20
20-NOV-11 1 -20 0
02-NOV-11 2 50 50
15-NOV-11 2 -50 0
6 rows selected.
and then use the running balance to find the zero dates.
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select date '2011-11-01' dt, 1 account, 100 amt from dual union all
3 select date '2011-11-02', 2, 50 from dual union all
4 select date '2011-11-03', 1, -100 from dual union all
5 select date '2011-11-07', 1, 20 from dual union all
6 select date '2011-11-15', 2, -50 from dual union all
7 select date '2011-11-20', 1, -20 from dual
8 )
9 select account,
10 dt zero_date
11 from (
12 select dt,
13 account,
14 amt,
15 sum(amt) over (partition by account order by dt) current_balance
16 from x
17 )
18* where current_balance = 0
SQL> /
ACCOUNT ZERO_DATE
---------- ---------
1 03-NOV-11
1 20-NOV-11
2 15-NOV-11
create table myacct (dt varchar2(5)
, account varchar2(3)
, amount number
)
;
insert into myacct values ('11/01', '001', 100);
insert into myacct values ('11/02', '002', 50);
insert into myacct values ('11/03', '001', -100);
insert into myacct values ('11/07', '001', 20);
insert into myacct values ('11/15', '002', -50);
insert into myacct values ('11/20', '001', -20);
commit;
/* results wanted:
Account ZeroDate
001 11/03
002 11/15
001 11/20 */
select account "Account", dt "ZeroDate"
from myacct
where amount <= 0
;
/* results from above query:
Account ZeroDate
001 11/03
002 11/15
001 11/20
*/