如何在SQL中计算日期差时排除周六、周日及周一?
解决方案:排除周六、周日、周一的工作日计算
针对你的需求,这里提供两种适用于SQL Server环境(你当前代码使用getdate(),推测为SQL Server)的实现方式:
方法一:递归CTE生成日期范围(直观易理解)
通过递归生成create_date到当前日期的所有日期,再统计其中不属于排除日期(周六、周日、周一)的数量:
WITH DateRange AS ( SELECT create_date AS DateVal FROM tickets UNION ALL SELECT DATEADD(day, 1, DateVal) FROM DateRange WHERE DateVal < GETDATE() ) SELECT t.ticket_id, t.status, t.create_date, CASE WHEN t.status = 'Open' THEN (SELECT COUNT(*) FROM DateRange dr WHERE dr.DateVal BETWEEN t.create_date AND GETDATE() -- 用iso_weekday避免DATEFIRST设置影响,周一=1、周日=7,排除周一、周六、周日 AND DATEPART(iso_weekday, dr.DateVal) NOT IN (1, 6, 7)) END AS sla FROM tickets t OPTION (MAXRECURSION 0); -- 日期跨度超过100天需开启,避免递归限制
方法二:数学公式计算(性能更优,适合大数据量)
通过计算总天数、完整周排除天数、剩余天数排除天数,直接得出有效工作日数,无需递归:
SELECT ticket_id, status, create_date, CASE WHEN status = 'Open' THEN -- 计算总天数(包含create_date和当前日期当天) DATEDIFF(day, create_date, GETDATE()) + 1 -- 减去完整周中需排除的天数(每周3天:周一、周六、周日) - (DATEDIFF(day, create_date, GETDATE()) + 1) / 7 * 3 -- 减去剩余零散天数中属于排除日期的数量 - ( SELECT COUNT(*) FROM (VALUES (1),(2),(3),(4),(5),(6)) AS RemainDays(n) WHERE n <= (DATEDIFF(day, create_date, GETDATE()) + 1) % 7 AND DATEPART(iso_weekday, DATEADD(day, n-1, create_date)) IN (1, 6, 7) ) END AS sla FROM tickets
注意事项
- 使用
DATEPART(iso_weekday, ...)可以避免服务器DATEFIRST设置的影响,确保星期判断准确(周一为1,周日为7) - 如果不需要包含
create_date或getdate()当天,调整总天数的计算逻辑(比如去掉+1) - 若
create_date晚于当前日期,可在CASE中额外处理(比如返回0或NULL)
内容的提问来源于stack exchange,提问作者Heber Brandao
相关产品推荐
相关产品推荐

