Oracle Function LAG和order by

时间:2018-02-12 17:15:50

标签: sql oracle lag

*编辑问题以反映真实输出,请参阅注释。

我有以下数据,我需要以前的程序。

表A

StartDate    EndDate     Program     Id 
  1/26/15     2/23/15      Red       1    
  2/24/15     3/31/17      Yellow    1
  5/3/16       6/1/17      Silver    1
  4/1/17       1/31/18     Orange    1
  2/1/18                   Blue      1

MyOutput中(不正确的)

StartDate    EndDate     Program      Prev_program   
  1/26/15     2/23/15      Red                    
  2/24/15     3/31/17      Yellow       Red
  5/3/16       6/1/17      Silver       Yellow
  4/1/17       1/31/18     Orange       Silver
  2/1/18                   Blue         Orange

ExpectedOutput:

StartDate    EndDate     Program      Prev_program   
  1/26/15     2/23/15      Red                    
  2/24/15     3/31/17      Yellow       Red
  5/3/16       6/1/17      Silver       Red
  4/1/17       1/31/18     Orange       Yellow
  2/1/18                   Blue         Orange

我希望在前一个程序结束日期不大于当前startdate时使用上一个程序。

我使用Lag产生了我不想要的结果。延迟不考虑"程序结束日期不大于当前的开始日期。"

SELECT *
,LAG (PROGRAM, 1) OVER (PARTITION BY ID ORDER BY STARTDATE) AS PREV_PROGRAM
FROM TABLEA

1 个答案:

答案 0 :(得分:1)

这是一种方法。不是最优雅或最有效的,但它确实起作用。两个索引,一个在(id, startdate)上,一个在(id, enddate)上可能有助于提高性能(无论如何都值得测试)。您缺少输出中的id列,但我认为它起作用(并且您希望为每个id单独完成处理)。我编写了查询以便为每个id单独工作,即使测试数据只有一个id

with子句不是查询的一部分 - 我将它包含在顶部而不是创建实际的表。你不需要它 - 从SELECT a1.startdate...

开始
with
  table_a ( startdate, enddate, program, id ) as (
    select date '2015-01-26', date '2015-02-23', 'Red'   , 1 from dual union all    
    select date '2015-02-24', date '2017-03-31', 'Yellow', 1 from dual union all
    select date '2016-03-05', date '2017-06-01', 'Silver', 1 from dual union all
    select date '2017-04-01', date '2018-01-31', 'Orange', 1 from dual union all
    select date '2018-02-01', null             , 'Blue'  , 1 from dual
  )
select   a1.startdate, a1.enddate, a1.program, a1.id,
         min(a2.program) keep (dense_rank last order by a2.startdate) as prev_program
from     table_a a1 left outer join table_a a2 
                    on a1.id = a2.id and a1.startdate > a2.enddate
group by a1.startdate, a1.enddate, a1.program, a1.id
;

STARTDATE   ENDDATE     PROGRAM   ID  PREV_PROGRAM
----------  ----------  --------  --  ------------
1/26/2015   2/23/2015   Red        1       
2/24/2015   3/31/2017   Yellow     1  Red   
3/5/2016    6/1/2017    Silver     1  Red   
4/1/2017    1/31/2018   Orange     1  Yellow
2/1/2018                Blue       1  Orange