2012-08-03 64 views
1

我在SQL Server 2012中,跟蹤登錄和退出時間,像這樣的表:(1型是登錄,2型是註銷)獲取時間跨度在同一列

UserId Type InsertDate 
2134  1  20120803 06:32:02.230 
2134  1  20120803 10:12:24.350 
2134  2  20120803 10:29:21.550 
2134  2  20120803 14:10:34.220 
5915  1  20120802 14:57:57.453 
5915  2  20120802 16:59:00.477 

我想查詢此表 - 顯示與計算的時間跨度用戶標識的每個登錄/註銷對秒的分組名單,所以我最終的東西,如:

UserID Duration 
2134  1017 
5915  7263 

UPDATE:對於單個用戶可以有多組登錄/註銷對,並且可能會有沒有相應註銷的登錄。我想忽略沒有相應值的登錄或註銷。

+2

如果什麼用戶有兩對條目?如果缺少類型1或類型2條目,該怎麼辦? – 2012-08-03 14:47:24

+3

是否有任何邊緣案例需要考慮?如果所有這些行都是針對同一個用戶的(這是可能的?),會有相同的結果(具有相同的用戶標識)還是單行 - 如果是單行,涵蓋最大期限?可以有多個'1'只有一個'2',反之亦然?根據你的簡單例子寫一個查詢很簡單,但我很好奇它與真實數據有多接近。 – 2012-08-03 14:49:03

+0

我建議爲其中一個用戶添加一個額外的登錄/註銷,並且可能僅添加一個僅具有登錄權限的用戶以及僅具有註銷的用戶,並更新所需的輸出,以便處理邊緣案例的期望很明確。 – 2012-08-03 15:57:06

回答

6

現在,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; 
+3

今天在sql server 2012中學習了一個新函數(Lag)。很好的答案! – praveen 2012-08-03 15:07:55

+0

太棒了 - 這個伎倆。還了解了滯後(和潛在客戶) - 非常全面的答案 – 2012-08-03 15:47:54

+0

@ChrisB樂於提供幫助。 MIN/MAX查詢當然要簡單得多,但它們只有在每個用戶只有一個登錄/註銷對的情況下才能工作。我假設問題中的示例數據被大大簡化,並且缺少多種類型的邊緣案例。 – 2012-08-03 15:49:07

0

嘗試

select datediff(s, min(InsertDate), max(InsertDate)) as diff 
from your_table 
group by UserId 
+0

這假定每個用戶在表中只有一對條目。 – 2012-08-03 14:52:40

0

如果只有一個登錄和註銷;

select UserId, DATEDIFF(second,Min(InsertDate),Max(InsertDate)) as Duration, 
from Table1 
Group By UserId 
+1

此答案與@ juergend的相同(除了將UserId列添加到輸出)。 – 2012-08-03 14:54:30

+0

是的,我沒有收到通知,寫我的答案。 – saj 2012-08-03 14:57:40