【问题标题】:Generating rows on days between multiple dates, counting days between each, and the first and last在多个日期之间的天数上生成行,计算每个日期之间的天数,以及第一个和最后一个日期
【发布时间】:2021-09-11 05:03:45
【问题描述】:

我需要在多个事件之间生成行,计算自一个事件和下一个事件以来的天数,以及“InitialEvent”和“ClosingEvent”之间的天数

这将显示从该事件是最近的事件到下一个事件发生之前的时间。见下表:

PersonID EventName DateID DaysSince_InitialEvent DaysSince_CurrentEvent DimensionID AnotherDimensionID etc
1 InitialEvent 20210501 - - - -
1 AnEvent1 20210505 - - - - -
1 AnEvent4 20210508 - - - - -
1 AnEvent2 20210511 - - - - -
1 ClosingEvent 20210513 - - - - -
2 InitialEvent 20210510 - - - - -
2 AnEvent1 20210513 - - - - -
2 ClosingEvent 20210510 - - - - -

我需要它来输出类似于下表的内容,它将显示每个事件在另一个事件发生之前已经存在多长时间:

PersonID EventName DateID DaysSince_InitialEvent DaysSince_CurrentEvent DimensionID AnotherDimensionID etc
1 InitialEvent 20210501 0 0 - -
1 InitialEvent 20210502 1 1 - -
1 InitialEvent 20210503 2 2 - -
1 InitialEvent 20210504 3 3 - -
1 AnEvent1 20210505 4 0 - -
1 AnEvent1 20210506 5 1 - -
1 AnEvent1 20210507 6 2 - -
1 AnEvent1 20210508 7 3 - -
1 AnEvent1 20210509 8 4 - -
1 AnEvent1 20210510 9 5 - -
1 AnEvent2 20210511 10 0 - -
1 AnEvent2 20210512 11 1 - -
1 ClosingEvent 20210513 12 0 - -
2 InitialEvent 20210510 0 0 - -
2 InitialEvent 20210511 1 1 - -
2 InitialEvent 20210512 2 2 - -
2 AnEvent1 20210513 3 0 - -
2 AnEvent1 20210514 4 1 - -
2 ClosingEvent 20210515 5 0 - -

有数千个 PersonID,每个可能有 20 到 30 个事件。一切都可以同时发生。也有大约 10 个维度,但这些都是静态的。

例如,我随后需要看到在 20210610 (2021-06-10) 上有两个活动事件:

  • PersonID 1,AnEvent1,距初始事件 9 天,距当前事件 5 天。
  • PersonID 2,InitialEvent,距初始事件 0 天,距当前事件 0 天。

我已经开始在 dim.date 表上创建 CTE 和交叉连接表,但完全迷失了。

谁能提出解决方案?

我希望问题清晰易懂。

列出了类似的问题here

【问题讨论】:

  • 请阅读this,了解一些改进问题的技巧。我们可以猜测DateIDint 吗?在任何地方都可以找到date 吗?如果只有 DDL 可以解密...... .

标签: sql sql-server tsql common-table-expression


【解决方案1】:

一种方法是递归 CTE:

with cte as (
      select personId, eventName, dateId, 0 as dayssincecurrentevent,
             dateadd(day, -1, lead(dateid) over (partition by personid order by dateid)) as end_dateid
      from t
      union all
      select personId, eventName, dateadd(day, 1, dateid) ,
             dayssincecurrentevent + 1,
             end_dateid
      from cte
      where dateid < end_dateid
     )
select personId, eventName, dateid, dayssincecurrentevent,
       datediff(day, min(dateid) over (partition by personid), dateid) as dayssinceinitialevent
from cte
order by personid, dateid;

Here 是一个 dbfiddle。

注意:如果某个日期的时间段可能超过 100 天,则需要在查询中添加 option (maxrecursion 0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 2019-09-27
    • 2021-07-08
    相关资源
    最近更新 更多