我正在尝试在SQL Server 2012中为报告创建一个SQL查询,并提出了以下查询。此查询使用临时表(EmpName, EntryDate, EntryTime, TrnName, TrnCode
)中的数据。
数据不一致并操纵它。下面的代码使用了level2中提到的多个场景,但我想编辑下面的查询,在最终时间计算之前为任何缺失的打孔(入口或出口)放置NULL值。
以下是样本数据。
EmpName EventDate EventTime TrnName TrnCode
A 2015-07-20 11:07:29.0000000 Entrance 0
A 2015-07-20 11:08:09.0000000 Exit 1
A 2015-07-20 21:13:27.0000000 Exit 1
A 2015-07-21 12:07:03.0000000 Entrance 0
A 2015-07-21 21:04:02.0000000 Exit 1
A 2015-07-22 11:48:06.0000000 Entrance 0
A 2015-07-22 13:57:58.0000000 Entrance 0
A 2015-07-22 13:37:15.0000000 Exit 1
A 2015-07-22 20:59:22.0000000 Exit 1
B 2016-06-20 23:03:33.0000000 Entrance 0
B 2016-06-21 02:36:38.0000000 Exit 1
B 2016-06-21 17:02:29.0000000 Entrance 0
B 2016-06-21 17:27:03.0000000 Entrance 0
B 2016-06-21 19:11:24.0000000 Exit 1
B 2016-06-21 19:24:41.0000000 Entrance 0
B 2016-06-21 23:35:25.0000000 Exit 1
B 2016-06-21 23:57:03.0000000 Entrance 0
B 2016-06-22 17:27:00.0000000 Exit 1
B 2016-06-22 17:42:01.0000000 Entrance 0
B 2016-06-22 19:37:43.0000000 Exit 1
B 2016-06-22 21:27:35.0000000 Entrance 0
B 2016-06-22 21:27:59.0000000 Exit 1
B 2016-06-22 21:45:47.0000000 Exit 1
B 2016-06-22 21:56:15.0000000 Entrance 0
B 2016-06-23 00:42:44.0000000 Exit 1
B 2016-06-23 01:03:06.0000000 Entrance 0
B 2016-06-23 02:47:18.0000000 Exit 1
我没有为每位员工设置任何固定班次时间,并且想要检查每次打卡之间的时差是否大于阈值(14小时),然后将OUT视为错误打卡或者通常计算小时差异。
;WITH Level1
AS (
SELECT
EmpName (or EmpID)
,TrnName (Exit or Entrance)
,CAST(EventDate AS DATETIME) + CAST(EventTime AS DATETIME) AS EntryDateTime
,LAG (TrnName, 1, 'N/A') OVER ( PARTITION BY EmpName ORDER BY EntryDateTime) AS LastEvent
,LEAD(TrnName, 1, 'N/A') OVER ( PARTITION BY EmpName ORDER BY EventDateTime ) AS NextEvent
FROM #TempData
),
Level2
AS (
SELECT
EmpName
,TrnName
,EntryDateTime
,LastEvent
,NextEvent
FROM Level1
WHERE
NOT ( TrnName = 'Entrance' AND NextEvent = 'Entrance' )
AND NOT ( TrnName = 'Entrance' AND LastEvent = 'Entrance' )
AND NOT ( TrnName = 'Exit' AND LastEvent = 'Exit' )
AND NOT ( TrnName = 'Entrance' AND NextEvent = 'N/A' )
AND NOT (TrnName = 'Exit' AND LastEvent = 'N/A' )
),
Level3
AS (
SELECT
EmpName
,TrnName
,EntryDateTime
,DATEDIFF(second, EntryDateTime,LEAD(EntryDateTime) OVER ( PARTITION BY EmpName ORDER BY EntryDateTime )) AS Seconds
FROM Level2
)
SELECT
EmpName
,EntryDateTime
,(EntryDateTime+convert(DateTime,TIMEFROMPARTS((Seconds%(3600*24)/3600), ((Seconds%(3600*24)%3600)/60), ((Seconds%(3600*24)%3600)%60),0, 0))) AS ExitDateTime
,Seconds
,TIMEFROMPARTS((Seconds%(3600*24)/3600), ((Seconds%(3600*24)%3600)/60), ((Seconds%(3600*24)%3600)%60),0, 0) AS WorkTime
FROM Level3
WHERE TrnName = 'Entrance'
预期结果:
Empname | EntryDateTime | ExitDateTime | Difference(Seconds) | Difference(hh:mm:ss)
A | 2015-07-20 11:07:29.000 | 2015-07-20 11:08:09.000 | 40 | 00:00:40
A | NULL | 2015-07-20 21:13:27.000 | NULL | NULL
A | 2015-07-21 12:07:03.000 | 2015-07-21 21:04:02.000 | 32219| 08:56:59
B | 2016-01-11 16:25:35.000 | 2016-01-11 17:59:42.000 | 5647 | 01:34:07
B | 2016-01-11 18:11:55.000 | 2016-01-11 20:18:48.000 | 7613 | 02:06:53
B | 2016-01-11 23:06:06.000 | NULL | NULL | NULL
B | 2016-01-12 00:29:17.000 | NULL | NULL | NULL
B | 2016-01-12 01:32:55.000 | 2016-01-12 01:39:54.000 | 419 | 00:06:59
B | 2016-06-21 23:57:03.000 | 2016-06-22 17:27:00.000 |62997 | 17:29:57
- 最后一条记录不正确,因为21-6-16的最后一次输入时间为输入,而外出时间为22-06-16的第一次输出。在这种情况下,OUT-Time值应为NULL,并且在下一条记录中,IN-Time值应为NULL,OUT时间为2016-06-22 17:27:00.000