我有一个 employee_attendance 表(SQL Server 2012
),其中包含以下列:
以下是 SQL小提琴,其中包含一些示例数据:http://sqlfiddle.com/#!3/ba8a1/1
我知道这些员工可以在我们拥有的3个班次中的任何一天工作:
所以我需要的是知道每个员工在选定的一天(样本数据只有一天,并且已过滤只显示 IN 记录,所以只有 IN 访问公司)是Shift入口附近(低于或高于)的第一个
Timestamp
。
以下是应用正确脚本后SQL Fiddle数据应该是什么样子的图像:
答案 0 :(得分:1)
由于你有SQL Server 2012,你可以使用TimeFromParts和“mod 8”来减少工作......
select employeeId,
accessCode,
minDiff = MIN(ABS(DATEDIFF(TIMEFROMPARTS(DATEPART(HH,t.timestamp) % 8,
(DATEPART(MI,t.timestamp),
(DATEPART(S,t.timestamp),0,0),
TIMEFROMPARTS(7,
(DATEPART(MI,t.timestamp),
(DATEPART(S,t.timestamp))
from table t
were t.timestamp is in a given daily range
所以,因为你的班次变化(7,15,23)都是“mod 8 = 7”我只是把时间戳“mod 8”的小时部分比作“7” - 这样我就不需要了运行查询三次。
答案 1 :(得分:0)
SQLFiddle(感谢您提供示例数据):http://sqlfiddle.com/#!3/ba8a1/7/0
查询:
declare @day datetime = '5-20-15' --not necessary, but included for more flexibility; you can just hardcode the date below if you want
SELECT *, '7:00:00 shift' as Shift
, abs(datediff(minute, timestamp, @day + '7:00:00')) as TimeDiff
into #temp
FROM employee_attendance
union all
SELECT *, '15:00:00 shift'
, abs(datediff(minute, timestamp, @day + '15:00:00'))
FROM employee_attendance
union all
SELECT *, '23:00:00 shift'
, abs(datediff(minute, timestamp, @day + '23:00:00'))
FROM employee_attendance
select * from (
select *
, row_number() over (partition by EmployeeID order by TimeDiff) as RowN
from #temp
) a
where RowN = 1
说明:
正如其他人所指出的那样,这假设员工每天只有一个轮班,并且离班次最接近的时钟是有效的。对于每天单班制,可能更有意义的是提出替代标准 - 例如,查看绝对最早的时钟输入,或者在给定窗口内最早的时钟输入(比如6:30到7: 30,对于7:00班次),但这不是这个请求者要求的。