我正在使用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可以做到吗?
答案 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的另一种方法。