2013-03-07 52 views
2

我有一個存儲員工聚集在datetime列的樞軸

登錄信息的表 的登錄表

樣本數據

EmpID Status  [Time] 
100 SignIn 2013-03-07 11:41:44.473 
101 SignIn 2013-03-07 10:41:44.473 
100 SignOut 2013-03-07 12:41:44.473 
101 SignOut 2013-03-07 11:41:44.473 
101 SignIn 2013-03-08 11:41:44.473 

我想要的結果是

EmpID SignIn     SignOut 
100 2013-03-07 11:41:44.473 2013-03-07 12:41:44.473 
101 2013-03-07 10:41:44.473 2013-03-07 11:41:44.473 
101 2013-03-08 11:41:44.473 NULL 

我試過使用PIVOT

Select EmpID,[SignIn],[SignOut] 
from 
(Select EmpId,status,LoginTime from Login)p 
pivot 
(
min(Logintime) 
For status in ([SignIn],[SignOut]) 
)pvt 

但上面的查詢省去了最後一排的Employee101SignIn時間,但no SignOut

SQLFiddle生成表數據

回答

3

你可以得到這樣的:

SELECT l1.EmpID 
     , l1.LoginTime [SignIn] 
     , l2.LoginTime [SignOut] 
FROM Login l1 
LEFT JOIN 
     Login l2 ON 
     l2.EmpID = l1.EmpID 
AND  CAST(l2.LoginTime AS DATE) = CAST(l1.LoginTime AS DATE) 
AND  l2.status = 'SignOut' 
WHERE l1.status = 'SignIn' 

注意,在如果您每天有多個員工登錄/註銷,並且您想要獲得第一個SignIn和最後一個SignOut一天,則必須更改查詢:

SELECT l1.EmpID 
     , MIN(l1.LoginTime) [SignIn] 
     , MAX(l2.LoginTime) [SignOut] 
FROM Login l1 
LEFT JOIN 
     Login l2 ON 
     l2.EmpID = l1.EmpID 
AND  CAST(l2.LoginTime AS DATE) = CAST(l1.LoginTime AS DATE) 
AND  l2.status = 'SignOut' 
WHERE l1.status = 'SignIn' 
GROUP BY 
     l1.EmpID, CAST(l1.LoginTime AS DATE) 

這裏是另一個查詢,也適用於同一天用戶的多個登錄/登出。這將列出他所有的登入/ signouts的一天:

;WITH cte1 AS 
(
    SELECT * 
      , ROW_NUMBER() OVER 
       (PARTITION BY EmpID, CAST(LoginTime AS DATE) ORDER BY LoginTime) 
       AS num 
    FROM Login 
) 

SELECT l1.EmpID 
     , l1.LoginTime [SignIn] 
     , l2.LoginTime [SignOut] 
FROM cte1 l1 
LEFT JOIN 
     cte1 l2 ON 
     l2.EmpID = l1.EmpID 
AND  CAST(l2.LoginTime AS DATE) = CAST(l1.LoginTime AS DATE) 
AND  l2.num = l1.num + 1 
WHERE l1.status = 'SignIn' 

這裏是SQL Fiddle對於處理用戶的多個登入/ signout場景在一天最後兩個查詢,爲此我添加用戶用EmpID 102來採樣數據。

+0

感謝您提供不同的解決方案! – praveen 2013-03-07 08:26:28

+1

不客氣,我認爲這可能是很好的覆蓋一些額外的情況,所以我添加了第二和第三個查詢。 – 2013-03-07 08:29:32

3

你是使用PIVOT功能在正確的軌道上,你只需要一種方式來分配row_number()基於該empidstatusdate每行/你可以使用下面的pivot代碼:

Select EmpID,[SignIn],[SignOut] 
from 
(
    Select EmpId, status, 
    LoginTime, 
    cast(logintime as date) date, 
    row_number() over(partition by empid, status, cast(logintime as date) 
         order by logintime) rn 
    from Login 
)p 
pivot 
(
    min(Logintime) 
    For status in ([SignIn],[SignOut]) 
)pvt 

參見SQL Fiddle with Demo

您會注意到子查詢中有兩個新列。一個爲每行生成一個row_number(),第二個在沒有時間的情況下生成date。這兩列均用於GROUP BY,但未在最終選擇中顯示。他們被使用,所以你可以每天爲每個員工獲得多行(如果需要的話)。

使用@ IvanG的數據從SQL小提琴的結果是:

| EMPID |    SIGNIN |    SIGNOUT | 
----------------------------------------------------- 
| 100 | 2013-03-07 11:41:44 | 2013-03-07 12:41:44 | 
| 101 | 2013-03-07 10:41:44 | 2013-03-07 11:41:44 | 
| 101 | 2013-03-08 11:41:44 |    (null) | 
| 102 | 2013-04-08 12:41:44 | 2013-04-08 13:41:44 | 
| 102 | 2013-04-08 16:41:44 | 2013-04-08 17:41:44 | 
| 102 | 2013-04-08 19:41:44 |    (null) | 
+1

@praveen我無法幫助它,我喜歡這些問題! :) – Taryn 2013-03-07 11:35:35

+1

當我看到這個問題是關於數據透視,並沒有解決,我認爲「bluefeet可能不在線」:) – 2013-03-07 11:44:01

+1

@IvanG人們只是期待我的答案是有點傷心! ':D' – Taryn 2013-03-07 11:45:06