Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Misconception about the LAG function's ... functionality?

chuckersOct 8 2008 — edited Mar 19 2009

So I want to look at the value of a column on a current row, and the value of the same column on the most recently entered row, prior to the current. The problem I'm encountering is that for the current row, I'm only interested in those added last month. So, if the record that I'm seeking in the LAG function is prior to last month, it gets rejected from the resultset.

create table check_lag
(filenr number, code varchar2(2), create_date date);

insert into check_lag values (1,'02',to_date('9/5/2008','MM/DD/YYYY')); -- current
insert into check_lag values (1,'01',to_date('9/1/2008','MM/DD/YYYY')); --lag record, same month
insert into check_lag values (2,'02',to_date('9/10/2008','MM/DD/YYYY'));-- current
insert into check_lag values (2,'01',to_date('8/10/2008','MM/DD/YYYY'));-- lag record prior month

So this query's results made sense

SELECT FILENR, CODE, 
       LAG( CODE ) OVER( PARTITION BY FILENR ORDER BY FILENR, CREATE_DATE ) AS PRIOR_CODE, 
       CREATE_DATE
FROM   CHECK_LAG;

FILENR CODE PRIOR_CODE CREATE_DATE
1      01              9/1/2008
1      02   01         9/5/2008
2      01              8/10/2008
2      02   01         9/10/2008

But as soon as I add a WHERE clause which set's a boundary around last month, I exclude a LAG record

SELECT FILENR, CODE, 
       LAG( CODE ) OVER( PARTITION BY FILENR ORDER BY FILENR, CREATE_DATE ) AS PRIOR_CODE, 
       CREATE_DATE
FROM   CHECK_LAG;

FILENR CODE PRIOR_CODE CREATE_DATE
1      01              9/1/2008
1      02   01         9/5/2008
2      02              9/10/2008

I know that I could push this into an inline view, and provide the WHERE clause with the date range after the inline view is processed, but this is a huge table with an index on the CREATE_DATE, and so the following forces a table scan

SELECT *
FROM   ( SELECT FILENR, CODE, 
                LAG( CODE ) OVER( PARTITION BY FILENR ORDER BY FILENR, CREATE_DATE ) AS PRIOR_CODE,
                CREATE_DATE
        FROM   CHECK_LAG )
WHERE  CREATE_DATE BETWEEN TO_DATE( '09/01/2008', 'MM/DD/YYYY' )
                       AND TO_DATE( '09/30/2008 23:59:59', 'MM/DD/YYYY HH24:MI:SS' )
AND    PRIOR_CODE IS NOT NULL;

FILENR CODE PRIOR_CODE CREATE_DATE
1      02   01         9/5/2008
2      02   01         9/10/2008

Is that just the way things are, or am I missing out on another approach?

Thanks,
Chuck

Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Nov 6 2008
Added on Oct 8 2008
5 comments
642 views