Tsql 查询时间卡数据库
我有一个时间表供员工打卡进出,布局如下:Tsql 查询时间卡数据库,tsql,Tsql,我有一个时间表供员工打卡进出,布局如下: employeeID Clock-in DateTime Clock Type 1004 24/09/2013 13:08 in 1004 25/09/2013 00:50 out 1005 24/09/2013 12:08 in 1005 25/09/2013 03:55 out 2003 24/09/2013 10:06 in 2003
employeeID Clock-in DateTime Clock Type
1004 24/09/2013 13:08 in
1004 25/09/2013 00:50 out
1005 24/09/2013 12:08 in
1005 25/09/2013 03:55 out
2003 24/09/2013 10:06 in
2003 24/09/2013 15:42 out
2003 24/09/2013 17:33 in
2003 24/09/2013 22:17 out
我怎样才能让它像:
Date employeeID Clock-in Clock-out time worked (in hours to 2 decimal place)
24/09/2013 1004 24/09/2013 13:08 25/09/2013 00:50 xx.xx
24/09/2013 1005 24/09/2013 12:08 25/09/2013 03:55 xx.xx
24/09/2013 2003 24/09/2013 10:06 24/09/2013 15:42 xx.xx
24/09/2013 2003 24/09/2013 17:33 24/09/2013 22:17 xx.xx
注:
员工可以有多个上班/下班时间,即早班/下午班、夜班
日期从04:00:00到03:59:59,即在上述示例中,所有日期均归类为2013年9月24日
我如何处理没有打卡的记录?我是否可以设置为空,时间等于下一个日期03:59:59?
提前谢谢
我根据jods的建议更新了以下内容:
3组输入/输出记录示例
EmployeeID CardDate PunchType
1000 21/09/2013 07:43 in
1000 21/09/2013 11:29 out
1000 21/09/2013 12:39 in
1000 21/09/2013 20:37 out
1000 21/09/2013 21:58 in
1000 22/09/2013 00:16 out
您的查询返回
Date EmployeeID clockInTime clockOutTime
21/09/2013 1000 07:43:57 00:16:22
21/09/2013 1000 21:58:40 11:29:22
如果您使用SQL SERVER 2005及更高版本。你可以试试这个
WITH cte AS (
SELECT
[employeeID]
,ti.ClockIn
,ClockOut = (SELECT MIN(t.ClockIn)
FROM timecard t
WHERE ti.employeeID = t.employeeID
AND t.Type = 'out'
AND t.ClockIn > ti.ClockIn
AND t.ClockIn < DATEADD(hour, 24 + 4 , CAST(CAST(ti.ClockIn AS DATE) AS datetime))
)
,NextDayLimit = DATEADD(SECOND, -1, DATEADD(hour, 24 + 4 , CAST(CAST(ti.ClockIn AS DATE) AS datetime)))
FROM timecard ti
WHERE Type = 'in'
)
SELECT
employeeID,
ClockIn,
ISNULL(ClockOut, NextDayLimit) AS ClockOut,
CAST(DATEDIFF(minute, ClockIn, ISNULL(ClockOut, NextDayLimit))/60.0 AS NUMERIC(19,2)) AS TimeWorked
from cte
ORDER BY employeeID, ClockIn
如果您使用SQL 2012,以下是使用LEAD的基本思想:
SELECT
ROUND(clockIn) as [date],
employeeId,
clockIn as clockInTime,
LEAD(clockIn) OVER (PARTITION BY employeeId, ROUND(clockIn) ORDER BY clockIn) as clockOutTime
FROM TimeCard
WHERE clockType = 'in'
然后,您可以通过计算时钟输入和时钟输出时间之间的差异来获得时间
这里有很多拐弯处的案例,但并非全部都在这里处理:
工作时间能跨越午夜吗?
如果第一个时钟输入是“输出”类型,该怎么办?
如果一排有两个“进”或两个“出”怎么办?
不过,没有打卡的情况是可以处理的。因为分区的最后一行的前导值为NULL
在SQL 2005中,有一个更健壮的选项:
WITH NumberedClockIn AS (
SELECT
ROUND(clockIn) as [date],
employeeId,
clockIn as clockTime,
clockType,
ROW_NUMBER() OVER (PARTITION BY employeeId, ROUND(clockIn) ORDER BY clockIn) as rn
FROM TimeCard
)
SELECT
IN.[date],
IN.employeeId,
IN.clockTime as clockInTime,
OUT.clockTime as clockOutTime
FROM NumberedClockIn IN
LEFT OUTER JOIN NumberedClockIn OUT
ON IN.[date] = OUT.[date]
AND IN.employeeId = OUT.employeeID
AND IN.rn + 1 = OUT.rn
WHERE IN.clockType = 'in'
AND OUT.clockType = 'out'
它更复杂,效率更低,但在面对无效的“输入”和“输出”序列时更健壮。同样,它处理无效序列的方式可能是,也可能不是您真正想要的行为。此表上没有PK吗?或者一个给定的员工是否可以在一分钟内不打卡,从而使整个记录唯一。您使用的是哪个版本的sqlserver?表中有一个主键,但它是以某种方式散列的。时钟输入和时钟输出都是秒,因此每个记录都是唯一的。我们使用的是SQL server 2008标准r2I尝试了您的解决方案,该解决方案适用于最多有2条时钟输入/时钟输出4条记录的员工,但我有一名员工有3套时钟输入/时钟输出,并且输入和输出记录中存在不匹配。我已经把一些原始数据样本和返回的结果集提交给您参考