【问题标题】:SQL date subtraction per subject with index date condition具有索引日期条件的每个主题的 SQL 日期减法
【发布时间】:2022-12-19 18:17:19
【问题描述】:

我有一个主题记录表,其中每个主题作为 1 个或多个具有开始/结束日期和索引日期的行:

SUBJECT BEGIN_DATE END_DATE INQUIRY_DATE
1 1988-01-01 2010-04-05 2022-05-06
1 2010-04-06 2022-10-02 2022-05-06
2 1996-09-24 2005-08-08 2022-10-01
2 2016-11-21 2022-04-04 2022-10-01
3 2005-01-01 2021-02-12 2022-03-21
4 1999-12-31 2015-07-16 2022-08-15
4 2015-07-20 2020-04-01 2022-08-15
4 2020-12-31 2022-10-01 2022-08-15

我想知道的是,对于每个主题,开始/结束范围是否连续涵盖查询日期之前的 3 个月(结束日期和下一个开始日期之间的间隔不超过 14 天)?例如受试者 1:他们在 1988-01-01 和 2022-10-02 之间进行了连续观察,所以是的,这个受试者的询问日期已经涵盖了 3 个月之前;而主题 2 则没有。

使用 SQL (snowflake) 并从类似这样的东西开始(显然不完整,只是不确定如何到达我想要的地方):

with lookback as (
select *, INQUIRY_DATE - interval '3 months' as look_back_3m from tbl)

select *, case when diff >= 14 then 1 else 0 end as flag from (
select SUBJECT, BEGIN_DATE - lag(END_DATE) over(partition by subject order by BEGIN_DATE) as diff from tbl) z

【问题讨论】:

    标签: sql date snowflake-cloud-data-platform data-wrangling


    【解决方案1】:

    第一步是您要过滤掉任何在您的 INQUIRY_DATE 之前 4 个月之前结束或在您的 INQUIRY_DATE 之后 1 个月开始的行,因为它们在您定义的 3 个月 + 14 天规则之外。

    所以一些增强的数据:

    with your_table(subject, begin_date, end_date, inquiry_date) as (
        select * from values
        (1, '1988-01-01'::date, '2010-04-05'::date, '2022-05-06'::date),
        (1, '2010-04-06'::date, '2022-10-02'::date, '2022-05-06'::date),
        (2, '1996-09-24'::date, '2005-08-08'::date, '2022-10-01'::date),
        (2, '2016-11-21'::date, '2022-04-04'::date, '2022-10-01'::date),
        (3, '2005-01-01'::date, '2021-02-12'::date, '2022-03-21'::date),
        (4, '1999-12-31'::date, '2015-07-16'::date, '2022-08-15'::date),
        (4, '2015-07-20'::date, '2020-04-01'::date, '2022-08-15'::date),
        (4, '2020-12-31'::date, '2022-10-01'::date, '2022-08-15'::date),
        (5, '2022-05-01'::date, '2022-06-01'::date, '2022-08-15'::date),
        (5, '2022-06-01'::date, '2022-07-01'::date, '2022-08-15'::date),
        (5, '2022-07-01'::date, '2022-08-01'::date, '2022-08-15'::date),
        (5, '2022-08-01'::date, '2022-10-01'::date, '2022-08-15'::date),
        (6, '2022-05-01'::date, '2022-05-10'::date, '2022-08-15'::date),
        (6, '2022-06-01'::date, '2022-06-10'::date, '2022-08-15'::date),
        (6, '2022-07-01'::date, '2022-07-10'::date, '2022-08-15'::date),
        (6, '2022-08-01'::date, '2022-10-01'::date, '2022-08-15'::date)
    )
    
    select * 
    from your_table
    where begin_date <= inquiry_date
       and end_date >= dateadd(month, -4, inquiry_date);
    

    给出:

    SUBJECT BEGIN_DATE END_DATE INQUIRY_DATE
    1 2010-04-06 2022-10-02 2022-05-06
    4 2020-12-31 2022-10-01 2022-08-15
    5 2022-05-01 2022-06-01 2022-08-15
    5 2022-06-01 2022-07-01 2022-08-15
    5 2022-07-01 2022-08-01 2022-08-15
    5 2022-08-01 2022-10-01 2022-08-15
    6 2022-05-01 2022-05-10 2022-08-15
    6 2022-06-01 2022-06-10 2022-08-15
    6 2022-07-01 2022-07-10 2022-08-15
    6 2022-08-01 2022-10-01 2022-08-15

    然后你想找到一系列的差距并使它们引起争议。

    就像是:

    select *
        ,lag(end_date) over(partition by subject order by begin_date) as prior_end
        ,datediff(days, prior_end, begin_date) as days_of_gap
        ,(begin_date - 14) <= prior_end as prior_overlapped
        ,iff(prior_overlapped, null, begin_date) as group_start_date
    from your_table
    where begin_date <= inquiry_date
       and end_date >= dateadd(month, -4, inquiry_date);
    

    然后您想问,任何链条是否在 INQUIRY_DATE 之前/之日开始 - 3 个月并在 INQUIRY_DATE 之日/之后结束。

    select
        subject
        ,begin_date
        ,end_date
        ,group_date
        ,dateadd(month, -3, inquiry_date) as req_start_date
        ,datediff(days, group_date, end_date) as days_of_streak
        ,end_date >= inquiry_date as rule_1
        ,group_date <= dateadd(month, -3, inquiry_date) as rule_2
    from (
        select *
            ,lag(group_start_date) ignore nulls over (partition by subject order by begin_date) as l_g_d
            ,nvl(group_start_date, l_g_d) as group_date
        from (
            select *
                ,lag(end_date) over(partition by subject order by begin_date) as prior_end
                ,iff((begin_date - 14) <= prior_end, null, begin_date) as group_start_date
            from your_table
            where begin_date <= inquiry_date
               and end_date >= dateadd(month, -4, inquiry_date)
        )
    )
    order by subject, begin_date
    ;
    

    给出:

    SUBJECT BEGIN_DATE END_DATE GROUP_DATE REQ_START_DATE DAYS_OF_STREAK RULE_1 RULE_2
    1 2010-04-06 2022-10-02 2010-04-06 2022-02-06 4,562 TRUE TRUE
    4 2020-12-31 2022-10-01 2020-12-31 2022-05-15 639 TRUE TRUE
    5 2022-05-01 2022-06-01 2022-05-01 2022-05-15 31 FALSE TRUE
    5 2022-06-01 2022-07-01 2022-05-01 2022-05-15 61 FALSE TRUE
    5 2022-07-01 2022-08-01 2022-05-01 2022-05-15 92 FALSE TRUE
    5 2022-08-01 2022-10-01 2022-05-01 2022-05-15 153 TRUE TRUE
    6 2022-05-01 2022-05-10 2022-05-01 2022-05-15 9 FALSE TRUE
    6 2022-06-01 2022-06-10 2022-06-01 2022-05-15 9 FALSE FALSE
    6 2022-07-01 2022-07-10 2022-07-01 2022-05-15 9 FALSE FALSE
    6 2022-08-01 2022-10-01 2022-08-01 2022-05-15 61 TRUE FALSE

    我们想要两个规则都为真的行..

    因此:

    select
        subject
        ,group_date
        ,inquiry_date
    from (
        select *
            ,lag(group_start_date) ignore nulls over (partition by subject order by begin_date) as l_g_d
            ,nvl(group_start_date, l_g_d) as group_date
        from (
            select *
                ,lag(end_date) over(partition by subject order by begin_date) as prior_end
                ,iff((begin_date - 14) <= prior_end, null, begin_date) as group_start_date
            from your_table
            where begin_date <= inquiry_date
               and end_date >= dateadd(month, -4, inquiry_date)
        )
    )
    where end_date >= inquiry_date
        and group_date <= dateadd(month, -3, inquiry_date)
    order by subject, begin_date
    ;
    

    给出:

    SUBJECT GROUP_DATE INQUIRY_DATE
    1 2010-04-06 2022-05-06
    4 2020-12-31 2022-08-15
    5 2022-05-01 2022-08-15

    【讨论】:

      猜你喜欢
      • 2019-05-18
      • 2012-03-30
      • 2013-12-05
      • 2021-04-11
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      相关资源
      最近更新 更多