Oracle 11中如何计算排除周末与节假日的工作日天数并用于CASE WHEN判断
解决方案:在Oracle 11g中计算排除周末和节假日的工作日天数
没问题,我来帮你调整这个查询,让它同时满足排除周末和节假日的需求。你的原查询已经能正确计算排除周末的工作日数,现在只需要减去这段日期范围内属于工作日的节假日数量,就能得到符合要求的有效工作日数。
核心思路
- 保留原逻辑计算排除周末的工作日总数(
Num_Week_Days) - 从你的节假日表中,统计出
start_date到end_date之间不是周末的节假日数量(因为周末的节假日已经被原查询排除,无需重复扣除) - 用
Num_Week_Days减去这个节假日数量,得到最终的有效工作日数
修改后的完整查询
SELECT TO_CHAR(start_date, 'YYYY-MM-DD "("DY")"') AS start_date, TO_CHAR(end_date, 'YYYY-MM-DD "("DY")"') AS end_date, -- 原逻辑:计算排除周末的工作日数 (TRUNC(end_date, 'IW') - TRUNC(start_date, 'IW')) * 5 / 7 + LEAST(TRUNC(end_date) - TRUNC(end_date, 'IW') + 1, 5) - LEAST(TRUNC(start_date) - TRUNC(start_date, 'IW'), 5) -- 减去范围内属于工作日的节假日数量 - ( SELECT COUNT(*) FROM holiday_calendar -- 替换成你的节假日表名 WHERE HolidayDates BETWEEN TRUNC(start_date) AND TRUNC(end_date) AND TO_CHAR(HolidayDates, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') NOT IN ('SAT', 'SUN') ) AS Num_Work_Days FROM table_name;
适配你的CASE WHEN需求
如果要把这个判断整合到CASE WHEN语句中,可以这样写:
SELECT start_date, end_date, CASE WHEN ( (TRUNC(end_date, 'IW') - TRUNC(start_date, 'IW')) * 5 / 7 + LEAST(TRUNC(end_date) - TRUNC(end_date, 'IW') + 1, 5) - LEAST(TRUNC(start_date) - TRUNC(start_date, 'IW'), 5) - ( SELECT COUNT(*) FROM holiday_calendar WHERE HolidayDates BETWEEN TRUNC(start_date) AND TRUNC(end_date) AND TO_CHAR(HolidayDates, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') NOT IN ('SAT', 'SUN') ) ) > 3 THEN 0 ELSE 1 -- 这里替换成你需要的其他业务逻辑 END AS result FROM table_name;
关键细节说明
- 使用
TRUNC()处理日期,避免时间部分干扰范围判断 TO_CHAR(HolidayDates, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH')确保不管数据库语言设置如何,都能正确识别周末(SAT/SUN)- 子查询只统计工作日的节假日,因为周末的节假日本来就不算在原
Num_Week_Days里,不需要重复扣除
验证你的示例
以你给出的例子:start_date='12/27/2018'(周四),end_date='01/02/2019'(周三),节假日表包含12/31/2018和01/01/2019:
- 原
Num_Week_Days计算:12/27、28、31、1/1、1/2 → 共5天 - 节假日统计:12/31(周一)、1/1(周二)都是工作日,所以扣除2天
- 最终有效工作日数:5-2=3,完全符合你的示例结果
内容的提问来源于stack exchange,提问作者faujong




