I can get a sequence - using rownum() OVER (order by <field>)
- or just rownum
(see below), but am struggling with getting a specific rownum/seq and the "previous" two rows.
The table is a list of dates, and each day date corresponds to a monthly date - not necessarily its current month, however. (Because of day-of-week, a Thurs/Fri that's in a next month could still be "in" the previous month's bucket).
My goal is to join the table to itself, get today's date, then get corresponding Monthly date. The problem I think I'm having is that in the WHERE clause of the outer-outer query, I cannot do:
where rnum between (DDate is not NULL) and ((DDate is not NULL) -2)
or something like that.
In short -
select t2.*
from (
select rownum rnum, t1.*
from (
select distinct to_char(r.MONTHLY, 'YYYY-MM-DD') as MDate,
to_char(l.DAILY, 'YYYY-MM-DD') as DDate
from Z_DATES l
right outer join Z_DATES r
on to_char(l.MONTHLY, 'YYYY-MM-DD') = to_char(r.MONTHLY, 'YYYY-MM-DD')
and to_char(l.DAILY, 'YYYY-MM-DD') = to_char(SYSDATE, 'YYYY-MM-DD')
order by 1
) t1
order by rnum
) t2
-- where DDate is not NULL
-- where rnum between 11 and 13
RNUM MDATE DDate
11 2013-04-29
12 2013-05-27
13 2013-07-01 2013-07-16
I think this does what you've described:
select to_char(monthly, 'YYYY-MM-DD') as mdate,
to_char(daily, 'YYYY-MM-DD') as ddate
from (
select distinct monthly,
max(case when daily = trunc(sysdate) then daily end)
over (partition by monthly) as daily,
dense_rank() over (order by monthly desc) as rn
from z_dates
where daily <= trunc(sysdate)
)
where rn <= 3
order by monthly;
The inner select gets today's date for the current pseudo-month and null otherwise, and assigns a rank to each month. The outer select then limits that to three rows. If you only wanted the value for two months ago (which is slightly unclear) then just make that = 3
instead of <= 3
. The filter where daily <= trunc(sysdate)
is in case there are any future dates, which is plausible from how you've described the table, but doesn't do any harm anyway.
If you do only want the two-months-prior date then it's even simpler, you don't need to do the max()
part or get ddate
:
select to_char(monthly, 'YYYY-MM-DD') as mdate
from (
select distinct monthly,
dense_rank() over (order by monthly desc) as rn
from z_dates
where daily <= trunc(sysdate)
)
where rn = 3;