按顺序对事件进行分组,定义序列t-SQL之间的最小周期

时间:2018-05-22 12:56:46

标签: tsql

我有一个名为tbl_events的事件表,看起来像这样:

PersonID    Date
1           30/03/2015
1           22/04/2015
1           30/06/2015
2           18/07/2016
2           09/12/2016
2           28/04/2017
3           01/10/2014
3           28/11/2016
3           28/11/2016
3           16/01/2017
4           13/04/2017
4           09/05/2017

我希望能够按照每个'序列'的开始日期对这些事件进行分组,并将序列定义为从每个PersonID的第一个识别到最后识别的事件的一系列事件。序列中的最后一个事件被定义为事件,此后一年内该PersonID没有后续事件。

我希望看到的结果如下:

PersonID    FirstDate   Sequence    Events
1           30/03/2015  1           3
2           18/07/2016  1           3
3           01/10/2014  1           1
3           28/11/2016  2           3
4           13/04/2017  1           2

我能够在Excel中识别序列并转动数据,但我需要能够在SQL中执行此操作。

以下是我在Excel中用于生成序列号的公式(我填充单元格C3,其中A列为PersonID,B为Date):

=+IF(A2<>A3,1,IF((B3-B2)<365,C2,C2+1))

我已经使用ROW_NUMBER加入了表格,以获取该ID的日期和上一个事件日期之间的差异,但我不确定从那里开始。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我的解决方案基于您提供的示例数据以及您的Excel公式。

-- easily consumable sample data
DECLARE @tbl_events TABLE (PersonId int, [date] date)
INSERT @tbl_events VALUES
(1,'20150330'),(1,'20150422'),(1,'20150630'),(2,'20160718'),(2,'20161209'),(2,'20170428'),
(3,'20141001'),(3,'20161128'),(3,'20161128'),(3,'20170116'),(4,'20170413'),(4,'20170509');

-- Solution
WITH groupings AS
(
  SELECT 
    PersonId, 
    FirstDate = MIN([date]) OVER (PARTITION BY personId ORDER BY [date]),
    NextDate  = LAG([date],1,[date]) OVER (PARTITION BY personId ORDER BY [date]),
    [date],
    grouper   = 
      DATEDIFF(DAY, MIN([date]) OVER (PARTITION BY personId ORDER BY [date]), [date]) / 365
  FROM @tbl_events
),
Prep AS
(
  SELECT 
    PersonId, 
    firstDate = IIF(grouper = 0, FirstDate, IIF(FirstDate = NextDate, [date],NextDate))
  FROM groupings
)
SELECT 
  PersonId, 
  FirstDate, 
  [Sequence] = ROW_NUMBER() OVER (PARTITION BY personId ORDER BY FirstDate),
  [Events] = COUNT(*)
FROM prep
GROUP BY personId, FirstDate;

<强>结果

PersonId    FirstDate  Sequence             Events
----------- ---------- -------------------- -----------
1           2015-03-30 1                    3
2           2016-07-18 1                    3
3           2014-10-01 1                    1
3           2016-11-28 2                    3
4           2017-04-13 1                    2

首先注意所有年份都有365天,但是,我使用365来模拟你的excel逻辑;这需要更新以说明闰年。接下来,就像你的excel公式一样 - 只有当有两个序列时才会正确; 如果有人说2015年1月1日,2016年1月10日,2017年1月1日,它就行不通。请告诉我们是否需要逻辑来适应上述情况。

最后,此解决方案使用需要SQL Server 2012+的LAG,如果您使用的是早期版本的SQL,则必须相应地更新查询。