sql - 如何根据打卡时间分配班次
问题描述
基于自动分配给员工的打卡时间班次
表 Trnevents:
emp_reader_id EVENTID DT
3 1 2019-07-14 17:00:00.000
3 0 2019-07-14 10:00:00.000
3 1 2019-07-13 17:50:00.000
3 0 2019-07-13 10:05:00.000
3 1 2019-07-12 16:00:00.000
3 0 2019-07-12 08:55:00.000
declare
@start_date date='2019-07-12'
,@end_date date ='2019-07-14'
;WITH ByDays AS
( -- Number the entry register in each day
SELECT
emp_reader_id,
dt AS T,
CONVERT(VARCHAR(10),dt,102) AS Day,
FLOOR(CONVERT(FLOAT,dt)) DayNumber,
ROW_NUMBER() OVER(PARTITION BY FLOOR(CONVERT(FLOAT,dt)) ORDER BY dt) InDay
FROM trnevents
where
(
CONVERT(VARCHAR(26), dt, 23) >= CONVERT(VARCHAR(26), @start_date, 23)
and CONVERT(VARCHAR(26), dt, 23) <=CONVERT(VARCHAR(26), @end_date, 23)
)
)
,Diffs AS
(
SELECT
E.Day,
E.emp_Reader_id,
E.T ET,
O.T OT,
O.T-E.T Diff,
DATEDIFF(S,E.T,O.T) DiffSeconds -- difference in seconds
FROM
(
SELECT
BE.emp_Reader_id,
BE.T,
BE.Day,
BE.InDay
FROM ByDays BE
WHERE BE.InDay % 2 = 1
) E -- Even rows
INNER JOIN
(
SELECT
BO.emp_reader_id,
BO.T,
BO.Day,
BO.InDay
FROM ByDays BO
WHERE BO.InDay % 2 = 0
) O -- Odd rows
ON E.InDay + 1 = O.InDay -- Join rows (1,2), (3,4) and so on
AND E.Day = O.Day -- in the same day
)
SELECT * FROM Diffs
DECLARE @start TIME(0) = '9:00 AM', @end TIME(0) = '18:00 PM';
WITH x(n) AS
(
SELECT TOP (DATEDIFF(HOUR, @start, @end) + 1)
rn = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_columns
ORDER BY [object_id]
)
SELECT
t = DATEADD(HOUR, n-1, @start)
,cast(DATEADD(HOUR, n-1, @start) as varchar(50))+' shift'
FROM x
ORDER BY t;
如果员工在上午 8.30 到 9.30 之间打卡,如果 9.30 到 10.30,则分配到 9.00 班次。它分配到 10.00 班次
预期输出:
Day emp_Reader_id ET OT Diff DiffSeconds Shift
2019.07.12 3 2019-07-12 08:55:00.000 2019-07-12 16:00:00.000 1900-01-01 07:05:00.000 25500 09:00:00 shift
2019.07.13 3 2019-07-13 10:05:00.000 2019-07-13 17:50:00.000 1900-01-01 07:45:00.000 27900 10:00:00 shift
2019.07.14 3 2019-07-14 12:00:00.000 2019-07-14 21:00:00.000 1900-01-01 07:00:00.000 25200 12:00:00 shift
解决方案
如果员工在上午 8.30 到 9.30 之间打卡,如果 9.30 到 10.30,则分配到 9.00 班次。它分配到 10.00 班次
如果我理解正确,您可以使用以下case
表达式:
select e.*,
(case when dt >= '08:30:00' and dt < '09:30:00'
then 'Shift 09:00'
when dt >= '09:30:00' and dt < '10:30:00'
then 'Shift 10:00'
end) as shift
from Trnevents e
如果您想要一个更通用的解决方案,其中休息时间为全天 30 分钟间隔,则减去 30 分钟并提取小时:
select e.*,
datepart(hour, dateadd(minute, -30, dt)) as shift
from e;
推荐阅读
- c - 我的多播服务器只能接收来自同一子网上的发件人的消息
- delphi-10-seattle - 将应用程序窗口发送到后台
- python - 从数据框中随机选择小时
- arrays - 无法迭代字典数组,因为它说“键入'Any'的值没有下标”
- utf-8 - gpload 抛出异常“错误:编码“UTF8”的无效字节序列:0xe5b82e”
- jquery - jQuery发布错误'必须是字符串类型'
- msp430 - MSP430,我怎样才能让它进入睡眠模式20分钟?
- javascript - 全部反应 ref 和查询选择器
- android - 我如何要求用户在登录我的 Android 应用程序时始终输入他的密码/使用指纹?
- dependencies - Gradle 不会下载 fabric-sdk-java 的依赖项