1. MSSQL实现工作时间计算
在MSSQL中实现工作时间计算,主要需要考虑到两个方面,一是如何定义工作日,二是如何计算工作时间。下面详细介绍如何实现。
1.1 如何定义工作日
通常情况下,我们把周一至周五的上班时间定义为工作日,其他时间为休息日。为了实现工作日的定义,我们可以创建一个日历表(calendar table),在该表中标记每一天是否属于工作日。
下面是日历表的创建代码:
CREATE TABLE calendar (
day DATE PRIMARY KEY,
is_workday BIT NOT NULL
)
GO
在日历表中,day表示日期,is_workday表示该日期是否是工作日,取值为0或1。
可以使用以下代码向日历表中插入数据:
INSERT INTO calendar (day, is_workday)
VALUES
('2022-01-01', 0), -- 休息日
('2022-01-02', 0), -- 休息日
('2022-01-03', 1), -- 工作日
('2022-01-04', 1), -- 工作日
('2022-01-05', 1), -- 工作日
('2022-01-06', 1), -- 工作日
('2022-01-07', 1), -- 工作日
('2022-01-08', 0) -- 休息日
GO
以上代码向日历表中插入了2022年1月1日至8日的数据。
1.2 如何计算工作时间
在定义了工作日之后,就可以计算工作时间。一种简单有效的方法是计算两个时间点之间的工作时间。计算方法如下:
1. 找到起始时间(start_datetime)所在的工作日,并计算该工作日的上班时间开始于该时间之后或之前。如果上班时间开始于该时间之后,则起始时间为该时间,否则起始时间为当天的上班时间开始时间。
2. 找到结束时间(end_datetime)所在的工作日,并计算该工作日的下班时间结束于该时间之前或之后。如果下班时间结束于该时间之前,则结束时间为该时间,否则结束时间为当天的下班时间结束时间。
3. 计算起始时间至结束时间的时间差,即为工作时间。
下面是计算工作时间的SQL代码:
DECLARE @start_datetime DATETIME = '2022-01-03 09:00:00',
@end_datetime DATETIME = '2022-01-06 18:00:00'
SELECT SUM(DATEDIFF(MINUTE, start_time, end_time)) AS work_minutes
FROM (
-- 找到起始工作日上班时间开始时间
SELECT start_datetime AS start_time,
MIN(DATEADD(MINUTE, work_minutes, start_datetime)) AS end_time
FROM (
SELECT @start_datetime AS start_datetime,
CAST(@start_datetime AS DATE) AS workday,
(SELECT is_workday FROM calendar WHERE day = CAST(@start_datetime AS DATE)) AS is_workday,
CAST('09:00:00' AS TIME) AS work_start_time,
CAST('17:00:00' AS TIME) AS work_end_time,
DATEDIFF(MINUTE, CAST('09:00:00' AS TIME), CAST('17:00:00' AS TIME)) AS work_minutes
) AS t
WHERE is_workday = 1 AND start_datetime >= DATEADD(HOUR, DATEPART(HOUR, work_start_time) - 1, CAST(workday AS DATETIME))
GROUP BY start_datetime, work_start_time
UNION ALL
-- 找到结束工作日下班时间结束时间
SELECT MAX(DATEADD(MINUTE, -work_minutes, end_datetime)) AS start_time,
end_datetime AS end_time
FROM (
SELECT @end_datetime AS end_datetime,
CAST(@end_datetime AS DATE) AS workday,
(SELECT is_workday FROM calendar WHERE day = CAST(@end_datetime AS DATE)) AS is_workday,
CAST('09:00:00' AS TIME) AS work_start_time,
CAST('17:00:00' AS TIME) AS work_end_time,
DATEDIFF(MINUTE, CAST('09:00:00' AS TIME), CAST('17:00:00' AS TIME)) AS work_minutes
) AS t
WHERE is_workday = 1 AND end_datetime <= DATEADD(HOUR, DATEPART(HOUR, work_end_time), CAST(workday AS DATETIME))
GROUP BY end_datetime, work_end_time
UNION ALL
-- 中间工作日时间差
SELECT DATEADD(DAY, 1, workday) AS start_time,
DATEADD(MINUTE, work_minutes, DATEADD(DAY, 1, workday)) AS end_time
FROM (
SELECT CAST(@start_datetime AS DATE) AS cur_workday,
DATEADD(DAY, 1, CAST(@start_datetime AS DATE)) AS workday,
(SELECT is_workday FROM calendar WHERE day = workday) AS is_workday,
CAST('09:00:00' AS TIME) AS work_start_time,
CAST('17:00:00' AS TIME) AS work_end_time,
DATEDIFF(MINUTE, CAST('09:00:00' AS TIME), CAST('17:00:00' AS TIME)) AS work_minutes
) AS t
WHERE is_workday = 1
AND DATEDIFF(DAY, cur_workday, CAST(@end_datetime AS DATE)) > 1
) AS t2
以上代码计算了2022年1月3日上午9点至1月6日下午6点之间的工作时间,单位为分钟。
2. 总结
本文介绍了如何在MSSQL中实现工作时间计算,包括如何定义工作日和如何计算工作时间。日历表的创建可以使用自己的方式进行调整,比如增加节假日标记等。如果需要计算不同的工作时间,可以根据实际情况进行调整。