Reputation: 303
I have a table like this :
ID
Submitted Date
00001
20-JUL-2018
00001
17-MAR-2017
00001
20-JUN-2019
00002
20-JUL-2018
00002
22-AUG-2018
00002
23-APR-2019
I want to calculate the no of days between latest two Submitted Date for each ID.
Like for ID = 00001 , the no of days should be 20-JUN-2019 - 20-JUL-2018.
I am using Oracle 11G.
Upvotes: 0
Views: 363
Reputation: 191520
A slight variation; you can find the previous date for each row, and also assign a ranking based on the date order:
select id, submitted_date,
lag(submitted_date) over (partition by id order by submitted_date) as previous_date,
dense_rank() over (partition by id order by submitted_date desc) as rnk
from your_table;
ID SUBMITTED_DATE PREVIOUS_DATE RNK
----- -------------- ------------- ----------
00001 2017-03-17 3
00001 2018-07-20 2017-03-17 2
00001 2019-06-20 2018-07-20 1
00002 2018-07-20 3
00002 2018-08-22 2018-07-20 2
00002 2019-04-23 2018-08-22 1
And then use that as an inline view to only get the latest date - which is ranked first:
select id, submitted_date, previous_date,
submitted_date - previous_date as diff
from
(
select id, submitted_date,
lag(submitted_date) over (partition by id order by submitted_date) as previous_date,
dense_rank() over (partition by id order by submitted_date desc) as rnk
from your_table
)
where rnk = 1;
ID SUBMITTED_DATE PREVIOUS_DATE DIFF
----- -------------- ------------- ----------
00001 2019-06-20 2018-07-20 335
00002 2019-04-23 2018-08-22 244
Upvotes: 0
Reputation: 35920
Try this:
SELECT ID,
MAX(SUBMITTED_DATE - PREV_SUBMITTED_DATE) AS DIFF
FROM
(SELECT ID, SUBMITTED_DATE,
LAG(SUBMITTED_DATE) OVER (PARTITION BY ID ORDER BY SUBMITTED_DATE) AS PREV_SUBMITTED_DATE
FROM
(SELECT ID, SUBMITTED_DATE,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY SUBMITTED_DATE DESC) AS RN
FROM TABLE)
WHERE RN <= 2)
GROUP BY ID;
Or
SELECT ID, MAX(DIFF) AS DIFF FROM
(SELECT ID,
NTH_VALUE(SUBMITTED_DATE,1) OVER (PARTITION BY ID ORDER BY SUBMITTED_DATE DESC) -
NTH_VALUE(SUBMITTED_DATE,2) OVER (PARTITION BY ID ORDER BY SUBMITTED_DATE DESC) AS DIFF
FROM TABLE)
GROUP BY ID;
Cheers!!
Upvotes: 0
Reputation: 1270773
One method uses lag()
and lead()
:
select t.*,
(submitted_date - prev_sd) as day_diff
from (select t.*,
lag(submitted_date) over (partition by id order by submitted_date) as prev_sd,
lead(submitted_date) over (partition by id order by submitted_date) as next_sd
from t
) t
where next_sd is null;
This method avoids any aggregation.
Upvotes: 2