SQL Server遍历时间序列数据

时间:2018-08-21 18:57:34

标签: sql sql-server database

我正在使用SQL Server,想知道是否可以遍历时间序列数据,直到满足特定条件并基于该标签将我的数据存储在其他表中?

例如,假设我有一个这样的表:

Id  Date       Some_kind_of_event
+--+----------+------------------
1  |2018-01-01|dsdf...
1  |2018-01-06|sdfs...
1  |2018-01-29|fsdfs...
2  |2018-05-10|sdfs...
2  |2018-05-11|fgdf...
2  |2018-05-12|asda...
3  |2018-02-15|sgsd...
3  |2018-02-16|rgw...
3  |2018-02-17|sgs...
3  |2018-02-28|sgs...

我想要得到的是,为每个密钥计算两个相邻事件之间的差异,并找出这两个相邻事件之间是否存在差异> 10天。如果是的话,我想停止迭代该特定键,并在其他表中将标签设置为“非活动”,否则为“活动”。完成一个键后,我们从另一个键开始。

因此,例如id = 1将获得标签“无效”,因为存在两个日期的差异大于10天。最终结果将是这样:

Id  Label       
+--+----------+
1  |inactive 
2  |active
3  |inactive 

任何想法该怎么做?使用SQL可以做到吗?

3 个答案:

答案 0 :(得分:2)

使用DBMS时,您需要摆脱反复思考的想法。相反,您需要尝试思考问题。 “不必考虑要对行进行的操作,而要考虑对列进行的操作。”

如果我理解正确,这是你要做什么?

CREATE TABLE SomeEvent (ID int, EventDate date, EventName varchar(10));
INSERT INTO SomeEvent
VALUES (1,'20180101','dsdf...'),
       (1,'20180106','sdfs...'),
       (1,'20180129','fsdfs..'),
       (2,'20180510','sdfs...'),
       (2,'20180511','fgdf...'),
       (2,'20180512','asda...'),
       (3,'20180215','sgsd...'),
       (3,'20180216','rgw....'),
       (3,'20180217','sgs....'),
       (3,'20180228','sgs....');
GO
WITH Gaps AS(
    SELECT *,
           DATEDIFF(DAY,LAG(EventDate) OVER (PARTITION BY ID ORDER BY EventDate),EventDate) AS EventGap
    FROM SomeEvent)
SELECT ID,
       CASE WHEN MAX(EventGap) > 10 THEN 'inactive' ELSE 'active' END AS Label
FROM Gaps
GROUP BY ID
ORDER BY ID;

GO
DROP TABLE SomeEvent;
GO

假定您正在使用SQL Server 2012+,因为它使用了LAG函数,并且SQL Server 2008不到12个月的任何支持。

答案 1 :(得分:0)

尝试一下。请注意,将@MyTable替换为您的实际表。

WITH Diffs AS (
SELECT
    Id
    ,DATEDIFF(DAY,[Date],LEAD([Date],1,0) OVER (ORDER BY [Id], [Date])) Diff
FROM @MyTable)

SELECT 
    Id
    ,CASE WHEN MAX(Diff) > 10 THEN 'Inactive' ELSE 'Active' END
FROM Diffs
GROUP BY Id

答案 2 :(得分:0)

只需分享另一种方法(无需CTE)。

SELECT 
    ID 
,   CASE WHEN SUM(TotalDays) = (MAX(CNT) - 1) THEN 'Active' ELSE 'Inactive' END Label
FROM (
SELECT 
    ID 
,   EventDate
,   CASE WHEN DATEDIFF(DAY, EventDate, LEAD(EventDate) OVER(PARTITION BY ID ORDER BY EventDate)) < 10 THEN 1 ELSE 0 END TotalDays
,   COUNT(ID) OVER(PARTITION BY ID) CNT
FROM EventsTable 
) D
GROUP BY ID

该方法将计算每个ID的记录数量,并通过当前下一个日期之间的日期差(以天为单位)获取TotalDays,如果差值小于10天,则给我1,否则给我0

然后进行比较,如果总天数等于每个ID拥有的记录数(减一),则将打印Active,否则打印Inactive。

这只是不使用CTE的另一种方法。