Frage

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 -

  1. get the rownum where the DDate is not null (there will only be one row, since it's based on SYSDATE)
  2. get MDate value from two rows previous (which is my final goal, the MDate two months prior - the only value I need)

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

War es hilfreich?

Lösung 2

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.

SQL Fiddle.

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;

SQL Fiddle.

Andere Tipps

With t1 the way you have it now, this should work:

select LAG(mdate, 2) over (order by mdate)
from (
    ...
) t1
where ddate is not null

I think it could be cleaned up some more after that (self-join may not even be necessary) if you rethink the problem with the LAG function in mind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top