我正在计算 Night_Start_Time、Night_Shift_End、Night_Shift_Duration
我们定义了 Night_Shift_Start_Time = 22:00 小时和 Night_Shift_End_Time = 06:00 小时。
要获得夜类资格,员工应工作至少 30 分钟,否则不会被视为夜类
例如;
- 03:00 pm - 22:29 pm,在这种情况下,员工仅工作 29 分钟,其中 少于30分钟,不属于夜类
- 03:00 pm -- 22:30 pm 这是夜类,因为该员工工作了 30 分钟。
- 上午 05:29 - 下午 2:00,员工工作了 31 分钟(06:00 - 05:29) 配备夜类
- 上午 05:31 - 下午 2:00,该员工夜类工作 29 分钟 不能视为夜类时间。
表格
CREATE TABLE #Shift
(Eid int,
Shift_Start datetime,
Shift_End datetime);
GO
INSERT INTO #Shift
VALUES
(1,'20170522 20:00:00.000','20170523 06:00:00.000'),
(2,'20170522 02:00:00.000','20170522 12:00:00.000'),
(3,'20170522 23:00:00.000','20170523 08:00:00.000'),
(4,'20170522 23:00:00.000','20170523 00:00:00.000'),
(5,'20170522 00:00:00.000','20170522 05:00:00.000'),
(6,'20170522 15:00:00.000','20170522 21:00:00.000');
GO
预期输出
Eid Shift_Start Shift_End Night_Start_Time Night_Shift_End Night_Shift_Duration
1 2017-05-22 20:00:00.000 2017-05-23 06:00:00.000 2017-05-22 22:00:00.000 2017-05-23 06:00:00.000 8
2 2017-05-22 02:00:00.000 2017-05-22 12:00:00.000 2017-05-22 02:00:00.000 2017-05-22 06:00:00.000 4
3 2017-05-22 23:00:00.000 2017-05-23 08:00:00.000 2017-05-22 23:00:00.000 2017-05-23 06:00:00.000 7
4 2017-05-22 23:00:00.000 2017-05-23 00:00:00.000 2017-05-22 23:00:00.000 2017-05-23 00:00:00.000 1
5 2017-05-22 00:00:00.000 2017-05-22 05:00:00.000 2017-05-22 00:00:00.000 2017-05-22 05:00:00.000 5
6 2017-05-22 15:00:00.000 2017-05-22 21:00:00.000 NULL NULL 0
最佳答案
请尝试以下代码...
SELECT Eid,
Shift_Start,
Shift_End,
CASE
WHEN DATEDIFF( S,
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END,
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '06:00:01' AND '22:29:59' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END
) >= 1800 THEN
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END
ELSE
NULL
END AS Night_Start_Time,
CASE
WHEN DATEDIFF( S,
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END,
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '06:00:01' AND '22:29:59' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END
) >= 1800 THEN
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '06:00:01' AND '22:29:59' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END
ELSE
NULL
END AS Night_Shift_End,
CASE
WHEN DATEDIFF( S,
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END,
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '06:00:01' AND '22:29:59' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END
) >= 1800 THEN
DATEDIFF( S,
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END,
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '06:00:01' AND '22:29:59' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END
) / 3600.0
ELSE
0.0
END AS Night_Shift_Duration
FROM #Shift;
该语句首先使用以下片段来选择夜类开始时间(而不是轮类开始时间)...
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END
此段提取 Shift_Start
的 TIME
组件并测试它是否超出夜类时间范围。如果是,那么它会提取 Shift_Start
的 DATE
组件并将其转换为字符串,以便可以将日期与夜类开始时间的字符串表示形式连接起来。然后,连接的字符串将转换为其等效的 DATETIME
值。
如果 Shift_Start
的 TIME
部分未落在夜类时间范围之外,则返回 Shift_Start
的值。
下面的语句使用类似的逻辑来确定夜类结束时间...
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END
如果记录的识别夜类结束时间超过 1800
秒(30
分钟以秒表示,允许以秒为单位的精确度)<在该记录识别的夜类开始时间之后,该记录的 Night_Start_Time
和 Night_Shift_End
字段将设置为其各自的夜类时间,并且Night_Shift_Duration
设置为它们之间的小时差,计算方式为秒差除以一小时内的秒数。
我已经针对使用您提供的脚本创建的数据库测试了我的语句(谢谢您),并达到了预期的结果。
如果您有任何问题或意见,请随时发表评论。
附录1
针对示例数据库运行以下语句以进行进一步测试...
INSERT INTO #Shift
VALUES ( 7,
'20170522 05:31:00',
'20170522 22:01:00' ),
( 8,
'20170522 04:31:00',
'20170522 22:01:00' );
附录2
以下语句是上述语句的变体,它使用子查询来确定每个记录的 Night_Start_Time
和 Night_Shift_End
值,没有考虑两者之间的差异。主查询使用如此生成的值来确定 Night_Start_Time
、Night_Shift_End
和 Night_Shift_Duration
的最终值。
我不确定哪个更有效。
SELECT Eid,
Shift_Start,
Shift_End,
CASE
WHEN DATEDIFF( S,
Night_Start_Time,
Night_Shift_End
) >= 1800 THEN
Night_Start_Time
ELSE
NULL
END AS Night_Start_Time,
CASE
WHEN DATEDIFF( S,
Night_Start_Time,
Night_Shift_End
) >= 1800 THEN
Night_Shift_End
ELSE
NULL
END AS Night_Shift_End,
CASE
WHEN DATEDIFF( S,
Night_Start_Time,
Night_Shift_End
) >= 1800 THEN
DATEDIFF( S,
Night_Start_Time,
Night_Shift_End
) / 3600.0
ELSE
0.0
END AS Night_Shift_Duration
FROM ( SELECT Eid,
Shift_Start,
Shift_End,
CASE
WHEN CAST( Shift_Start AS TIME ) BETWEEN '05:30:01' AND '22:00:00' THEN
CAST( ( CAST( CAST( Shift_Start AS DATE ) AS VARCHAR ) + ' 22:00' ) AS DATETIME )
ELSE
Shift_Start
END Night_Start_Time,
CASE
WHEN CAST( Shift_End AS TIME ) BETWEEN '06:00:01' AND '22:29:59' THEN
CAST( ( CAST( CAST( Shift_End AS DATE ) AS VARCHAR ) + ' 06:00' ) AS DATETIME )
ELSE
Shift_End
END Night_Shift_End
FROM #Shift
) AS shiftTimesFinder;
关于sql - 计算夜类时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44125934/