如何对任意表达式描述的日期排序事件进行分组/窗口化?

时间:2016-05-10 17:46:52

标签: sql-server sql-server-2014 window-functions

我想根据日期和一些(可能是任意的)指标将一些数据组合在一起:

Date       | Ind
================
2016-01-02 | 1
2016-01-03 | 5
2016-03-02 | 10
2016-03-05 | 15
2016-05-10 | 6
2016-05-11 | 2

我想将后续(按日期排序)的行组合在一起,但在Indicator >= 10后打破该组:

Date       | Ind | Group
========================
2016-01-02 | 1   |   1
2016-01-03 | 5   |   1
2016-03-02 | 10  |   1

2016-03-05 | 15  |   2

2016-05-10 | 6   |   3
2016-05-11 | 2   |   3

我确实在博客文章末尾发现了一种很有前途的技术:" Use this Neat Window Function Trick to Calculate Time Differences in a Time Series" (最后一小节," Extra Bonus"),但查询的重要部分使用了一个似乎在SQL Server中不受支持的关键字(FILTER)(并且快速谷歌稍后,我不确定它在哪里支持!)。

我仍然希望使用窗口功能的技术可能就是答案。我只需要一个可以添加到每一行的计数器(如RANKROW_NUMBER那样),但只有当某个任意条件的计算结果为true时才会递增。有没有办法在SQL Server中执行此操作?

2 个答案:

答案 0 :(得分:3)

以下是解决方案:

PostWrapper

当前一行大于Post其他DECLARE @t TABLE ([Date] DATETIME, Ind INT) INSERT INTO @t VALUES ('2016-01-02', 1), ('2016-01-03', 5), ('2016-03-02', 10), ('2016-03-05', 15), ('2016-05-10', 6), ('2016-05-11', 2) SELECT [Date], Ind, 1 + SUM([Group]) OVER(ORDER BY [Date]) AS [Group] FROM ( SELECT *, CASE WHEN LAG(ind) OVER(ORDER BY [Date]) >= 10 THEN 1 ELSE 0 END AS [Group] FROM @t ) t 时,只需将行标记为1。然后一个运行总和将给你想要的结果。

答案 1 :(得分:1)

充分赞扬Giorgi的想法,但我已经修改了他的答案(为了我的利益和未来的读者)。

只需更改CASE语句,查看自上次记录以来是否已超过30天:

DECLARE @t TABLE ([Date] DATETIME)

INSERT INTO @t 
VALUES
('2016-01-02'),
('2016-01-03'),
('2016-03-02'),
('2016-03-05'),
('2016-05-10'),
('2016-05-11')

SELECT [Date],
       1 + SUM([Group]) OVER(ORDER BY [Date]) AS [Group]
FROM 
(
    SELECT  [Date], 
            CASE WHEN DATEADD(d, -30, [Date]) >= LAG([Date]) OVER(ORDER BY [Date])
                THEN 1 
                ELSE 0 
            END AS [Group] 
      FROM @t
) t