解决方案:
DECLARE @Event TABLE(
EventID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CardNo VARCHAR(10) NOT NULL,
[Login] DATETIME NOT NULL
-- To prevent duplicate events
-- This constraint will create an index used to optimize the RowNum and the last queries
UNIQUE(CardNo,[Login])
);
INSERT INTO @Event(CardNo,[Login])
SELECT 'E44920', '2013-07-15T09:18:00'
UNION ALL SELECT 'E44920', '2013-07-15T09:46:00'
UNION ALL SELECT 'E44920', '2013-07-15T17:09:00'
UNION ALL SELECT 'E44920', '2013-07-15T16:57:00'
UNION ALL SELECT 'E44920', '2013-07-15T17:34:00'
UNION ALL SELECT 'E44920', '2013-07-15T17:53:00';
DECLARE @EventWithRowNum TABLE(
RowNum INT NOT NULL,
CardNo VARCHAR(10) NOT NULL,
PRIMARY KEY (CardNo,RowNum),
[Login] DATETIME NOT NULL
UNIQUE(CardNo,[Login])
);
INSERT INTO @EventWithRowNum (CardNo,[Login],RowNum)
SELECT e.CardNo, e.[Login], ROW_NUMBER() OVER(PARTITION BY e.CardNo ORDER BY e.[Login]) AS RowNum
FROM @Event e;
-- Final query
SELECT crt.RowNum,
crt.CardNo,
crt.[Login] AS CurrentLogin,
nxt.RowNum,
nxt.[Login] AS NextLogin,
DATEDIFF(SECOND, crt.Login, nxt.Login) AS Diff_Seconds
FROM @EventWithRowNum crt -- crt = odd rows
LEFT JOIN @EventWithRowNum nxt ON crt.CardNo=nxt.CardNo AND crt.RowNum=nxt.RowNum-1 -- nxt = even rows
WHERE crt.RowNum % 2 = 1 -- odd rows; you could add a computed column Modulo2 AS (RowNum % 2) PERSISTED and then you could define a index (key: Modulo2, CardNo, Login)
ORDER BY crt.CardNo, crt.[Login];
结果:
RowNum CardNo Current_Login RowNum Next_Login Diff_Seconds
----------- ---------- ----------------------- ----------- ----------------------- ------------
1 E44920 2013-07-15 09:18:00.000 2 2013-07-15 09:46:00.000 1680
3 E44920 2013-07-15 16:57:00.000 4 2013-07-15 17:09:00.000 720
5 E44920 2013-07-15 17:34:00.000 6 2013-07-15 17:53:00.000 1140