【问题标题】:Oracle SQL: LAG over a range of valuesOracle SQL:在一系列值上滞后
【发布时间】:2020-09-08 15:35:43
【问题描述】:

我们如何在值的范围内使用分析函数 LAG。 如果分区中没有 in_date 较早的记录,则返回 null,否则返回上一个 in_date 的年份和月份

例子:

CID  IN_DATE        
1    2020-05-29
1    2020-06-10
1    2020-06-21
1    2020-07-08
1    2020-08-11
1    2020-10-01
2    2020-05-05
2    2020-05-03
2    2020-06-01
2    2020-06-02
2    2020-06-03

预期输出,

CID  IN_DATE        LAG
1    2020-05-29     null
1    2020-06-10     2020-05
1    2020-06-21     2020-05
1    2020-07-08     2020-06
1    2020-08-11     2020-07
1    2020-10-01     2020-08
2    2020-05-05     null 
2    2020-05-03     null
2    2020-06-01     2020-05
2    2020-06-02     2020-05
2    2020-06-03     2020-05
2    2020-07-03     2020-06
2    2020-08-13     2020-07

我当前使用 LAG 的查询返回如下

with data as (
select 1  CID,  TO_DATE('2020-05-29','YYYY-MM-DD')  IN_DATE from dual union all
select 1,  TO_DATE('2020-06-10','YYYY-MM-DD') from dual union all
select 1,  TO_DATE('2020-06-21','YYYY-MM-DD')  from dual union all
select 1,  TO_DATE('2020-07-08','YYYY-MM-DD') from dual union all
select 1,  TO_DATE('2020-08-11','YYYY-MM-DD') from dual union all
select 2,  TO_DATE('2020-05-05','YYYY-MM-DD') from dual union all
select 2,  TO_DATE('2020-05-03','YYYY-MM-DD') from dual union all
select 2,  TO_DATE('2020-06-01','YYYY-MM-DD') from dual union all
select 2,  TO_DATE('2020-06-02','YYYY-MM-DD') from dual union all
select 2,  TO_DATE('2020-06-03','YYYY-MM-DD') from dual 
    ) 
    select CID, 
           to_char(TO_DATE(IN_DATE), 'YYYY-MM-DD') IN_DATE, 
           LAG(to_char(TO_DATE(IN_DATE), 'YYYY-MM')) OVER (PARTITION BY CID 
                                                           ORDER BY to_char(TO_DATE(IN_DATE), 'YYYY-MM') ) LAG 
    from data

当前结果

    CID IN_DATE     LAG
1   1   2020-05-29  NULL
2   1   2020-06-10  2020-05
3   1   2020-06-21  2020-06
4   1   2020-07-08  2020-06
5   1   2020-08-11  2020-07
6   2   2020-05-05  NULL
7   2   2020-05-03  2020-05
8   2   2020-06-01  2020-05
9   2   2020-06-02  2020-06
10  2   2020-06-03  2020-06

看起来,LAG 不允许我们使用超出范围的分区 是否有替代方法

【问题讨论】:

    标签: sql oracle plsql oracle12c analytic-functions


    【解决方案1】:

    如果您想要在此之前的上个月,您不想要 LAG()。我建议:

    with data as (
        select 1  CID,  TO_DATE('2020-05-29','YYYY-MM-DD')  IN_DATE from dual union all
        select 1,  TO_DATE('2020-06-10','YYYY-MM-DD') from dual union all
        select 1,  TO_DATE('2020-06-21','YYYY-MM-DD')  from dual union all
        select 1,  TO_DATE('2020-07-08','YYYY-MM-DD') from dual union all
        select 1,  TO_DATE('2020-08-11','YYYY-MM-DD') from dual union all
        select 2,  TO_DATE('2020-05-05','YYYY-MM-DD') from dual union all
        select 2,  TO_DATE('2020-05-03','YYYY-MM-DD') from dual union all
        select 2,  TO_DATE('2020-06-01','YYYY-MM-DD') from dual union all
        select 2,  TO_DATE('2020-06-02','YYYY-MM-DD') from dual union all
        select 2,  TO_DATE('2020-06-03','YYYY-MM-DD') from dual 
        ) 
    select CID, 
           to_char(TO_DATE(IN_DATE), 'YYYY-MM-DD') IN_DATE, 
           TO_CHAR(MAX(IN_DATE) OVER (PARTITION BY CID 
                                      ORDER BY TRUNC(IN_DATE, 'MON')
                                      RANGE BETWEEN UNBOUNDED PRECEDING AND INTERVAL '1' MONTH PRECEDING
                                     ),
                   'YYYY-MM') as LAG 
    from data;
    

    Here 是一个 dbfiddle。

    【讨论】:

    • 谢谢。这回答了我的问题
    【解决方案2】:

    记录 7 的 Lag 字段不为空,因为滞后函数正在查找记录 6。

    我可以看到两种方法来澄清你的问题:

    1. 如果分区中没有 in_date 更早的记录,您想返回 null

    2. 如果in_date在当前记录的in_date前一个月的分区中没有记录,则要返回null

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      相关资源
      最近更新 更多