我有一个存储员工登录信息的表
登录表的示例数据是
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
但上述查询遗漏了Employee
101
SignIn
时间no SignOut
值
SQLFiddle用于生成表格数据
答案 0 :(得分: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)
这是另一个查询,也适用于同一天用户的多次登录/注销。这将在一天内列出他所有的登录/注销:
;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 ,用于处理一天内用户的多个登录/注销方案的最后两个查询,为此我添加了EmpID
102的用户样本数据。
答案 1 :(得分:3)
您使用PIVOT
功能走在正确的轨道上,您只需要根据row_number()
,empid
和{status
为每行分配一个date
{1}} /您可以使用以下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
您会注意到子查询中有两个新列。一个为每行生成row_number()
,第二个生成date
,没有时间。这两列都在GROUP BY
中使用,但未在最终选择中显示。它们被使用,因此您可以每天为每位员工获取多行(如果需要)。
使用来自sql小提琴的@ IvanG数据的结果是:
| 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) |