如何使用SQL计算两个日期之间不含节假日的工作日?
计算两个日期间的工作日(不含节假日)SQL实现
核心思路是:先计算日期范围内的总周一至周五天数,再减去该范围内属于工作日的节假日数量。通过维护统一的节假日表替代手动计算,后续仅需更新表数据即可。
第一步:创建统一的节假日表
先建立一张用于管理所有节假日的表,结构简单易维护:
-- MySQL/PostgreSQL/SQL Server通用表结构 CREATE TABLE holidays ( holiday_date DATE PRIMARY KEY, description VARCHAR(100) -- 可选,标注节假日名称 );
你可以手动插入节假日数据,或通过脚本批量导入每年的法定假日,比如:
INSERT INTO holidays (holiday_date, description) VALUES ('2024-01-01', '元旦'), ('2024-02-10', '春节'), ('2024-04-04', '清明节');
第二步:分数据库实现计算逻辑
以下是主流SQL数据库的具体查询代码,替换对应日期变量为你的目标日期即可。
MySQL
SET @start_date = '2024-01-01'; SET @end_date = '2024-01-31'; SELECT -- 计算总周一至周五天数 (DATEDIFF(@end_date, @start_date) + 1 - FLOOR((DATEDIFF(@end_date, @start_date) + WEEKDAY(@start_date)) / 7) * 2 - CASE WHEN WEEKDAY(@start_date) = 5 THEN 1 ELSE 0 END -- 排除起始日为周六的情况 - CASE WHEN WEEKDAY(@end_date) = 6 THEN 1 ELSE 0 END) -- 排除结束日为周日的情况 -- 减去属于工作日的节假日数量 - (SELECT COUNT(*) FROM holidays WHERE holiday_date BETWEEN @start_date AND @end_date AND WEEKDAY(holiday_date) NOT IN (5, 6)) AS working_days;
注:MySQL中WEEKDAY()返回0=周一,5=周六,6=周日。
PostgreSQL
WITH date_range AS ( SELECT generate_series('2024-01-01'::DATE, '2024-01-31'::DATE, '1 day') AS date ) SELECT -- 统计日期范围内的周一至周五数量 COUNT(*) -- 减去属于工作日的节假日数量 - (SELECT COUNT(*) FROM holidays WHERE holiday_date BETWEEN '2024-01-01' AND '2024-01-31' AND EXTRACT(DOW FROM holiday_date) NOT IN (0, 6)) AS working_days FROM date_range WHERE EXTRACT(DOW FROM date) NOT IN (0, 6); -- 0=周日,6=周六
SQL Server
DECLARE @start_date DATE = '2024-01-01'; DECLARE @end_date DATE = '2024-01-31'; SELECT -- 计算总周一至周五天数 (DATEDIFF(day, @start_date, @end_date) + 1) - (DATEDIFF(week, @start_date, @end_date) * 2) - CASE WHEN DATEPART(weekday, @start_date) = 1 THEN 1 ELSE 0 END -- 排除起始日为周日 - CASE WHEN DATEPART(weekday, @end_date) = 7 THEN 1 ELSE 0 END -- 排除结束日为周六 -- 减去属于工作日的节假日数量 - (SELECT COUNT(*) FROM holidays WHERE holiday_date BETWEEN @start_date AND @end_date AND DATEPART(weekday, holiday_date) NOT IN (1, 7)) AS working_days;
注:SQL Server默认DATEPART(weekday)返回1=周日,7=周六,若你的数据库设置不同需调整对应数值。
注意事项
- 上述计算包含起始日和结束日,若不需要包含某一端,调整日期范围或DATEDIFF参数即可。
- 节假日表需定期更新,比如每年年初导入当年的法定节假日,确保计算准确。
内容的提问来源于stack exchange,提问作者erdemhho
相关产品推荐
相关产品推荐

