SQL - Selecting the rows with max timestamp by group - sql

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

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

SQL: How to deal with NULL and PARTITION BY?

I've got a question, if you don't mind terribly.
So suppose I have this kind of a table here – Products (amount sold by quarter in 2000, only there are multiple entries for the same product and quarter (with different dates)):
product
quarter
amount sold
Jeans
1
20
Jeans
2
40
Jeans
3
60
Jeans
4
5
Skirt
1
10
Skirt
2
5
Skirt
3
30
Blouse
1
15
Blouse
2
40
Blouse
3
60
Blouse
4
15
I want to reintroduce it as follows:
product
quarter1
quarter2
quarter3
quarter4
Jeans
20
40
60
5
Skirt
10
5
30
Null
Blouse
15
40
60
15
I decided to do it with partition (cause it's not exactly that simple, there are different rows with the same quarter for the same product, but different amount sold, that's why it's sum(amount_sold), but you get the idea, I hope):
WITH quater_sales as(
SELECT DISTINCT pro.product, pro.quarter, to_char (sum(pro.amount_sold) OVER (PARTITION BY pro.product, pro.quarter)) AS quater
FROM products pro
ORDER BY pro.pro.product)
SELECT quater_sales.prod_product, quater_sales.quater AS "Q1", qu2.quater AS "Q2", qu3.quater AS "Q3", qu4.quater AS "Q4"
FROM quater_sales
JOIN quater_sales qu2 ON quater_sales.prod_subcategory=qu2.prod_subcategory
JOIN quater_sales qu3 ON quater_sales.prod_subcategory=qu3.prod_subcategory
JOIN quater_sales qu4 ON quater_sales.prod_subcategory=qu4.prod_subcategory
WHERE quater_sales.calendar_quarter_number=1 and qu2.calendar_quarter_number=2 and qu3.calendar_quarter_number=3 and qu4.calendar_quarter_number=4
The problem is with partition (or maybe it's the condition of select) that the product that was not sold in all the 4 quarters is just discarded. What I basically get in the end is this:
product
quarter1
quarter2
quarter3
quarter4
Jeans
20
40
60
5
Blouse
15
40
60
15
So how do I make "skirts" appear there too? I am a bit stuck with this.
Have you considered using a PIVOT statement?
WITH
quarter_sales (product, quarter, amount_sold)
AS
(SELECT 'Jeans', 1, 20 FROM DUAL
UNION ALL
SELECT 'Jeans', 2, 40 FROM DUAL
UNION ALL
SELECT 'Jeans', 3, 60 FROM DUAL
UNION ALL
SELECT 'Jeans', 4, 5 FROM DUAL
UNION ALL
SELECT 'Skirt', 1, 10 FROM DUAL
UNION ALL
SELECT 'Skirt', 2, 5 FROM DUAL
UNION ALL
SELECT 'Skirt', 3, 30 FROM DUAL
UNION ALL
SELECT 'Blouse', 1, 15 FROM DUAL
UNION ALL
SELECT 'Blouse', 2, 40 FROM DUAL
UNION ALL
SELECT 'Blouse', 3, 60 FROM DUAL
UNION ALL
SELECT 'Blouse', 4, 15 FROM DUAL)
SELECT *
FROM (SELECT *
FROM quarter_sales qs)
PIVOT (SUM (amount_sold)
FOR quarter
IN (1 AS quarter1, 2 AS quarter2, 3 AS quarter3, 4 AS quarter4));
PRODUCT QUARTER1 QUARTER2 QUARTER3 QUARTER4
__________ ___________ ___________ ___________ ___________
Blouse 15 40 60 15
Jeans 20 40 60 5
Skirt 10 5 30
try pivot. this is how you would pivot in tsql
declare #tmp as table(product varchar(20),quarter int,[amount sold] int);
insert into #tmp values
('Jeans', 1, 20)
,('Jeans', 2, 40)
,('Jeans', 3, 60)
,('Jeans', 4, 5)
,('Skirt', 1, 10)
,('Skirt', 2, 5)
,('Skirt', 3, 30)
,('Blouse', 1, 15)
,('Blouse', 2, 40)
,('Blouse', 3, 60)
,('Blouse', 4, 15)
select product, [1] as quarter1,[2] as quarter2,[3] as quarter3,[4] as quarter4
from
(
select product,quarter,[amount sold] from #tmp)p
pivot
(
sum([amount sold])
for quarter in([1],[2],[3],[4])
) as pvt
output:
product quarter1 quarter2 quarter3 quarter4
Blouse 15 40 60 15
Jeans 20 40 60 5
Skirt 10 5 30 NULL

how to join 2 tables in SQL oracle

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>

sqHow to get sum values weekly based between two dates?

My table values like ...
Date Amt Cash Money Name
15-Jun 100 10 20 GUL
16-Jun 200 20 40 ABC
20-Jun 300 30 60 GUL
25-Jun 400 40 80 BCA
28-Jun 500 50 10 GUL
3-Jul 600 60 120 ABC
19-Jun 700 70 140 BCA
26-Jun 800 80 160 ABC
7-Jul 900 90 180 GUL
9-Jul 1000 100 200 ABC
I need to return weekly based sum of values between two date in oracle .My expected output.
Date Amt Cash Mony
13 to 19 June 1000 100 200
20 to 26 June 1500 150 300
27 to3 July 1100 110 130
4 to 10 July 1900 190 380
you can achieve this by a case statement:
e.g.
-- test data
with data(dat,
val1,
val2) as
(select sysdate - 7, 12, 13
from dual
union all
select sysdate - 6, 32, 1
from dual
union all
select sysdate - 5, 52, 53
from dual
union all
select sysdate - 4, 2, 16
from dual
union all
select sysdate - 3, 72, 154
from dual)
select -- build up your groups
case
when d.dat < to_date('28.09.2016', 'DD.MM.YYYY') then
'<28.09.'
when d.dat > to_date('30.09.2016', 'DD.MM.YYYY') then
'>30.09.'
else
'28.-30.'
end as grp,
sum(val1),
sum(val2)
from data d
group by case
when d.dat < to_date('28.09.2016', 'DD.MM.YYYY') then
'<28.09.'
when d.dat > to_date('30.09.2016', 'DD.MM.YYYY') then
'>30.09.'
else
'28.-30.'
end;
-- output
grp sum(val1) sum(val2)
28.-30. 84 54
<28.09. 12 13
>30.09. 74 170
To group by calendar week use
-- test data
with data(dat,
val1,
val2) as
(select sysdate - 9, 12, 13
from dual
union all
select sysdate - 6, 32, 1
from dual
union all
select sysdate - 5, 52, 53
from dual
union all
select sysdate - 4, 2, 16
from dual
union all
select sysdate + 3, 72, 154
from dual)
select TRUNC(dat, 'iw') ||'-'|| TRUNC(dat+7, 'iw'),
sum(val1),
sum(val2)
from data
group by TRUNC(dat, 'iw') ||'-'|| TRUNC(dat+7, 'iw');
The query below has the input dates (from and to) in the first factored subquery. Those can be made into bind variables, or whatever mechanism you want to use to pass these inputs to the query. Then I have the test data in the second factored subquery; you don't need that in your final solution. I create all the needed weeks in the "weeks" factored subquery and I use a left outer join, so that weeks with no transactions will show 0 sums. Note that in the main query, where I do a join, the "date" column from the base table is not enclosed within any kind of function; this allows the use of an index on that column, which you should have if the table is very large, or if performance may be a concern for any other reason. Note that the output is different from yours (missing the last row) because I input a to-date before the last row in the table. That is intentional, I wanted to make sure the query works correctly. Also: I didn't use "date" or "week" as column names; that is a very poor practice. Reserved Oracle keywords should not be used as column names. I used "dt" and "wk" instead.
with
user_inputs ( from_dt, to_dt ) as (
select to_date('4-Jun-2016', 'dd-Mon-yyyy'), to_date('3-Jul-2016', 'dd-Mon-yyyy') from dual
),
test_data ( dt, amt, cash, money, name ) as (
select to_date('15-Jun-2016', 'dd-Mon-yyyy'), 100, 10, 20, 'GUL' from dual union all
select to_date('16-Jun-2016', 'dd-Mon-yyyy'), 200, 20, 40, 'ABC' from dual union all
select to_date('20-Jun-2016', 'dd-Mon-yyyy'), 300, 30, 60, 'GUL' from dual union all
select to_date('25-Jun-2016', 'dd-Mon-yyyy'), 400, 40, 80, 'BCA' from dual union all
select to_date('28-Jun-2016', 'dd-Mon-yyyy'), 500, 50, 10, 'GUL' from dual union all
select to_date( '3-Jul-2016', 'dd-Mon-yyyy'), 600, 60, 120, 'ABC' from dual union all
select to_date('19-Jun-2016', 'dd-Mon-yyyy'), 700, 70, 140, 'BCA' from dual union all
select to_date('26-Jun-2016', 'dd-Mon-yyyy'), 800, 80, 160, 'ABC' from dual union all
select to_date( '7-Jul-2016', 'dd-Mon-yyyy'), 900, 90, 180, 'GUL' from dual union all
select to_date( '9-Jul-2016', 'dd-Mon-yyyy'), 1000, 100, 200, 'ABC' from dual
),
weeks ( start_dt ) as (
select trunc(from_dt, 'iw') + 7 * (level - 1)
from user_inputs
connect by level <= 1 + (to_dt - trunc(from_dt, 'iw')) / 7
)
select to_char(w.start_dt, 'dd-Mon-yyyy') || ' - ' ||
to_char(w.start_dt + 6, 'dd-Mon-yyyy') as wk,
nvl(sum(t.amt), 0) as tot_amt, nvl(sum(t.cash), 0) as tot_cash,
nvl(sum(t.money), 0) as tot_money
from weeks w left outer join test_data t
on t.dt >= w.start_dt and t.dt < w.start_dt + 7
group by start_dt
order by start_dt
;
Output:
WK TOT_AMT TOT_CASH TOT_MONEY
-------------------------------------------- ---------- ---------- ----------
30-May-2016 - 05-Jun-2016 0 0 0
06-Jun-2016 - 12-Jun-2016 0 0 0
13-Jun-2016 - 19-Jun-2016 1000 100 200
20-Jun-2016 - 26-Jun-2016 1500 150 300
27-Jun-2016 - 03-Jul-2016 1100 110 130
You can try like below, I chose 13-Jun-2016 as a starting date. You can chose it as per your requirement upto any range of dates.
with t as
(select dt,
min(dt) over (partition by week)||' to '|| max(dt) over (partition by week) week
from (
select to_date('13-Jun-2016','dd-Mon-yyyy')+(level-1) dt,
ceil(level/7) week
from dual
connect by level<=52))
select week,
sum(amt),
sum(cash),
sum(money)
from (
select your_table.*,
t.week
from your_table,t
where trunc(to_date(your_table.dt,'dd-Mon-yyyy'))=trunc(t.dt))
group by week;

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
*/