【问题标题】:sql that finds records within 3 days of a condition being met在满足条件后 3 天内查找记录的 sql
【发布时间】:2021-08-03 23:50:10
【问题描述】:

我正在尝试查找在事件发生之前的某个日期范围内存在的所有记录。在下表中,我想提取从开关字段从 0 变为 1 后 3 天或更短的所有记录,按日期排序,按产品分区。我的解决方案不起作用,它包括应该跳过的第一条记录,因为它在 3 天窗口之外。我正在扫描一个包含数百万条记录的表,有没有办法在保持我想要的结果的同时降低复杂性/成本?

http://sqlfiddle.com/#!18/eebe7

CREATE TABLE productlist
    ([product] varchar(13), [switch] int, [switchday] date)
;

INSERT INTO productlist
    ([product], [switch], [switchday])
VALUES
    ('a', 0, '2019-12-28'),
    ('a', 0, '2020-01-02'),
    ('a', 1, '2020-01-03'),
    ('a', 0, '2020-01-06'),
    ('a', 0, '2020-01-07'),
    ('a', 1, '2020-01-09'),
    ('a', 1, '2020-01-10'),
    ('a', 1, '2020-01-11'),
    ('b', 1, '2020-01-01'),
    ('b', 0, '2020-01-02'),
    ('b', 0, '2020-01-03'),
    ('b', 1, '2020-01-04')
;  

我的解决方案:

with switches as (
SELECT
  *,
  case when lead(switch) over (partition by product order by switchday)=1
    and switch=0 then 'first day switch'
    else null end as leadswitch
  from productlist
  ),
 switchdays as (
   select * from switches
   where leadswitch='first day switch'
   )
 select pl.*
 ,'lead'
 from productlist pl
 left join switchdays ss
 on pl.product=ss.product
 and pl.switchday = ss.switchday
 and datediff(day, pl.switchday, ss.switchday)<=3
 where pl.switch=0  

所需的输出,捕获在从 0 到 1 的切换后 3 天内发生的记录,对于每个产品,按日期排序:

product switch  switchday   
a   0   2020-01-02  lead
a   0   2020-01-06  lead
a   0   2020-01-07  lead
b   0   2020-01-02  lead
b   0   2020-01-03  lead

【问题讨论】:

    标签: sql sql-server window-functions


    【解决方案1】:

    如果我理解正确,您可以使用两次lead()

    select pl.*
    from (select pl.*,
                 lead(switch) over (partition by product order by switchday) as next_switch_1,
                 lead(switch, 2) over (partition by product order by switchday) as next_switch_2
          from productlist pl
         ) pl
    where switch = 0 and
          1 in (next_switch_1, next_switch_2);
    

    Here 是一个 dbfiddle。

    编辑(基于评论):

    select pl.*
    from (select pl.*,
                 min(case when switch = 1 then switchdate end) over (partition by product order by switchdate desc) as next_switch_1_day
          from productlist pl
         ) pl
    where switch = 0 and
          next_switch_one_day <= dateadd(day, 2, switchdate);
    

    【讨论】:

    • 抱歉,Gordon 含糊不清,我的示例遗漏了一个重要的边缘案例。我不是简单地寻找上面有铅的行,我正在寻找 3 天内的日期(重要)。因此,例如,如果您将第一个日期更改为 2019 年,那将是一年后,但仍会显示在您的结果中 dbfiddle.uk/…
    • @barker。 . .我为该场景添加了一个替代版本。
    • 嗯,我改变了你的解决方案(我认为是错别字),但我相信它仍然缺少一些日子,让我改变我的问题以包括边缘情况。 dbfiddle.uk/…
    猜你喜欢
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多