如何在轮班附近的一天内获得第一个员工入口

VAA*_*AAA 5 sql sql-server sql-server-2008

我有一个employee_attendance表(SQL Server 2012),其中包含以下列:

  • 出勤率(身份)
  • 员工ID
  • 时间戳(打卡或打卡)
  • AccessCode(I = IN,O = OUT)

这是SQL Fiddle的一些示例数据:http://sqlfiddle.com/#!3/ba8a1/1

我知道这些员工可以在我们拥有的3个班次中的任何一天工作:

  1. 班次A(从07:00到15:00)
  2. 班次B(从15:00到23:00)
  3. Shift C(次日23:00至次日07:00)

所以我需要的是在选定的一天知道每个员工(样本数据只有一天并且已被过滤以仅显示IN记录,因此只有IN访问公司)是第一个Timestamp接近(低于或高于)转移入口.

下面是应用正确脚本后SQL Fiddle数据应该是什么样子的图像:

在此输入图像描述

APH*_*APH 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
Run Code Online (Sandbox Code Playgroud)

解释:

  1. 为每个员工的每个轮班开始时间创建一行。
  2. 计算实际开始时间与列出的打卡时间之间的差异。取绝对值,因为原始请求是寻找最近的打卡时间,不一定是在轮班开始之前。
  3. 使用 row_number 来标识与轮班开始时间相差最短的每个员工的行。
  4. 仅返回距离班次开始时间最近的行。

正如其他人所指出的,这假设一名员工每天只有一个轮班,并且最接近轮班时间的打卡时间是有效的。对于每天一个班次的系统,提出替代标准可能更有意义 - 例如,查看绝对最早的打卡上班时间,或给定窗口内的最早打卡上班时间(例如 6:30 到 7:30) 30,7:00 轮班),但这不是该请求者所要求的。