如何根据滚动的 30 天窗口 SQL 选择行

Posted

技术标签:

【中文标题】如何根据滚动的 30 天窗口 SQL 选择行【英文标题】:How to select rows based on a rolling 30 day window SQL 【发布时间】:2021-07-21 00:36:54 【问题描述】:

我的问题涉及如何识别指数放电。

指数放电是最早的放电。在该日期,30 天窗口开始。在此期间的任何入院都被视为重新入院,应该被忽略。一旦 30 天窗口期结束,任何后续排放都将被视为一个指数,30 天窗口期将再次开始。

我似乎无法弄清楚这其中的逻辑。我尝试过不同的窗口函数,我尝试过交叉连接和交叉应用。我一直遇到的问题是重新入院不能是索引入院。它必须被排除。

我已经成功编写了一个 while 循环来解决这个问题,但如果可能的话,我真的很想以基于集合的格式来获得它。到目前为止我还没有成功。

最终目标是这个-

id AdmitDate DischargeDate MedicalRecordNumber IndexYN
1 2021-03-03 00:00:00.000 2021-03-09 13:20:00.000 X0090362 1
4 2021-03-05 00:00:00.000 2021-03-10 16:00:00.000 X0012614 1
6 2021-05-18 00:00:00.000 2021-05-21 22:20:00.000 X0012614 1
7 2021-06-21 00:00:00.000 2021-07-08 13:30:00.000 X0012614 1
8 2021-02-03 00:00:00.000 2021-02-09 17:00:00.000 X0019655 1
10 2021-03-23 00:00:00.000 2021-03-26 16:40:00.000 X0019655 1
11 2021-03-15 00:00:00.000 2021-03-18 15:53:00.000 X4135958 1
13 2021-05-17 00:00:00.000 2021-05-23 14:55:00.000 X4135958 1
15 2021-06-24 00:00:00.000 2021-07-13 15:06:00.000 X4135958 1

示例代码如下。

CREATE TABLE #Admissions
  (
     [id]                INT,     
     [AdmitDate]         DATETIME,
     [DischargeDateTime] DATETIME,
     [UnitNumber]        VARCHAR(20),
     [IndexYN]           INT
  ) 

  INSERT INTO #Admissions
  VALUES( 1  ,'2021-03-03'  ,'2021-03-09 13:20:00.000'  ,'X0090362', NULL)
        ,(2  ,'2021-03-27'  ,'2021-03-30 19:59:00.000'  ,'X0090362', NULL)
        ,(3  ,'2021-03-31'  ,'2021-04-04 05:57:00.000'  ,'X0090362', NULL)
        ,(4  ,'2021-03-05'  ,'2021-03-10 16:00:00.000'  ,'X0012614', NULL)
        ,(5  ,'2021-03-28'  ,'2021-04-16 13:55:00.000'  ,'X0012614', NULL)
        ,(6  ,'2021-05-18'  ,'2021-05-21 22:20:00.000'  ,'X0012614', NULL)
        ,(7  ,'2021-06-21'  ,'2021-07-08 13:30:00.000'  ,'X0012614', NULL)
        ,(8  ,'2021-02-03'  ,'2021-02-09 17:00:00.000'  ,'X0019655', NULL)
        ,(9  ,'2021-02-17'  ,'2021-02-22 17:25:00.000'  ,'X0019655', NULL)
        ,(10 ,'2021-03-23'  ,'2021-03-26 16:40:00.000'  ,'X0019655', NULL)
        ,(11 ,'2021-03-15'  ,'2021-03-18 15:53:00.000'  ,'X4135958', NULL)
        ,(12 ,'2021-04-08'  ,'2021-04-13 19:42:00.000'  ,'X4135958', NULL)
        ,(13 ,'2021-05-17'  ,'2021-05-23 14:55:00.000'  ,'X4135958', NULL)
        ,(14 ,'2021-06-09'  ,'2021-06-14 12:45:00.000'  ,'X4135958', NULL)
        ,(15 ,'2021-06-24'  ,'2021-07-13 15:06:00.000'  ,'X4135958', NULL)

【问题讨论】:

如果您可以发布您的 while 循环代码,这将有助于理解问题。 请向我们展示您的尝试以及您遇到的问题。 【参考方案1】:

您可以使用递归 CTE 来识别与每个“索引”放电相关的所有行:

with a as (
      select a.*, row_number() over (order by dischargedatetime) as seqnum
      from admissions a
     ),
     cte as (
      select id, admitdate, dischargedatetime, unitnumber, seqnum, dischargedatetime as index_dischargedatetime
      from a
      where seqnum = 1
      union all
      select a.id, a.admitdate, a.dischargedatetime, a.unitnumber, a.seqnum,
             (case when a.dischargedatetime > dateadd(day, 30, cte.index_dischargedatetime)
                   then a.dischargedatetime else cte.index_dischargedatetime
              end) as index_dischargedatetime
      from cte join
           a
           on a.seqnum = cte.seqnum + 1
     )
select *
from cte;

然后您可以将其合并到update

update admissions
    set indexyn = (case when admissions.dischargedatetime = cte.index_dischargedatetime then 'Y' else 'N' end)
    from cte
    where cte.id = admissions.id;

Here 是一个 dbfiddle。请注意,我将IndexYN 的类型更改为分配'Y'/'N' 的字符,考虑到列名,这很有意义。

【讨论】:

以上是关于如何根据滚动的 30 天窗口 SQL 选择行的主要内容,如果未能解决你的问题,请参考以下文章

根据最近的日期窗口选择结果

Pandas 按天滚动时间窗口而不是单个行

如何根据 3 个不同的列在 mysql 中选择行

Cypress web自动化30-操作窗口滚动条(scrollTo)

Cypress web自动化30-操作窗口滚动条(scrollTo)

SQL如何根据多行中的值选择行