现在,SQL Server 2012使自联接和聚集有点不必要。该解决方案可处理同一用户的多次登录。
DECLARE @t TABLE(UserID INT, [Type] TINYINT, InsertDate DATETIME);
INSERT @t VALUES
(2134,1,'20120803 10:12:24.350'),
(2134,2,'20120803 10:29:21.550'),
(2134,1,'20120803 11:22:24.350'),
(2134,2,'20120803 11:47:21.550'),
(5915,1,'20120802 14:57:57.453'),
(5915,2,'20120802 16:59:00.477');
;WITH x AS (
SELECT UserID, [Type], InsertDate, Prev = LAG(InsertDate, 1) OVER
(PARTITION BY UserID ORDER BY InsertDate) FROM @t
)
SELECT UserID, DATEDIFF(SECOND, Prev, InsertDate) FROM x WHERE [Type] = 2;
-- or if you want cumulative time per user even if there are multiple login events:
;WITH x AS (
SELECT UserID, [Type], InsertDate, Prev = LAG(InsertDate, 1) OVER
(PARTITION BY UserID ORDER BY InsertDate) FROM @t
)
SELECT UserID, SUM(DATEDIFF(SECOND, Prev, InsertDate))
FROM x WHERE [Type] = 2 GROUP BY UserID;
在以前的版本中,你可以使用更复杂的:
;WITH x AS
(
SELECT UserID, [Type], InsertDate,
rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY InsertDate)
FROM @t
)
SELECT x.UserID, DATEDIFF(SECOND, x.InsertDate, y.InsertDate)
FROM x INNER JOIN x AS y
ON x.UserID = y.UserID
AND x.rn = y.rn - 1
WHERE x.Type = 1
AND y.Type = 2;
如果什么用户有两对条目?如果缺少类型1或类型2条目,该怎么办? – 2012-08-03 14:47:24
是否有任何边缘案例需要考虑?如果所有这些行都是针对同一个用户的(这是可能的?),会有相同的结果(具有相同的用户标识)还是单行 - 如果是单行,涵盖最大期限?可以有多个'1'只有一个'2',反之亦然?根据你的简单例子写一个查询很简单,但我很好奇它与真实数据有多接近。 – 2012-08-03 14:49:03
我建议为其中一个用户添加一个额外的登录/注销,并且可能仅添加一个仅具有登录权限的用户以及仅具有注销的用户,并更新所需的输出,以便处理边缘案例的期望很明确。 – 2012-08-03 15:57:06