如何统计上月周五、周六和周日的天数?
计算上月周五、周六、周日的总天数(SQL Server)
需求说明
需要统计上月内周五、周六、周日这三天的总天数。你已正确定义上月的起止日期:
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0) AS start_date, DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) - 1, -1) AS last_date
但之前尝试的代码仅针对周六周日计算,且逻辑存在偏差,无法满足包含周五的统计需求。
解决方案1:日期差公式计算(无需生成日期序列)
通过计算每个目标星期几在日期范围内的出现次数,再求和。注意SQL Server中DATEPART(dw, ...)的返回值受DATEFIRST设置影响,默认DATEFIRST=7(周日为一周第一天),对应:周日=1、周五=6、周六=7。
DECLARE @start_date DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0); DECLARE @last_date DATE = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) - 1, -1); -- 统一设置周日为一周第一天,避免环境差异 SET DATEFIRST 7; SELECT -- 统计周五数量 (DATEDIFF(WEEK, @start_date, @last_date) + CASE WHEN DATEPART(dw, @start_date) <= 6 THEN 1 ELSE 0 END - CASE WHEN DATEPART(dw, @last_date) < 6 THEN 1 ELSE 0 END) AS friday_count, -- 统计周六数量 (DATEDIFF(WEEK, @start_date, @last_date) + CASE WHEN DATEPART(dw, @start_date) <= 7 THEN 1 ELSE 0 END - CASE WHEN DATEPART(dw, @last_date) < 7 THEN 1 ELSE 0 END) AS saturday_count, -- 统计周日数量 (DATEDIFF(WEEK, @start_date, @last_date) + CASE WHEN DATEPART(dw, @start_date) <= 1 THEN 1 ELSE 0 END - CASE WHEN DATEPART(dw, @last_date) < 1 THEN 1 ELSE 0 END) AS sunday_count, -- 三天总天数 ( (DATEDIFF(WEEK, @start_date, @last_date) + CASE WHEN DATEPART(dw, @start_date) <= 6 THEN 1 ELSE 0 END - CASE WHEN DATEPART(dw, @last_date) < 6 THEN 1 ELSE 0 END) + (DATEDIFF(WEEK, @start_date, @last_date) + CASE WHEN DATEPART(dw, @start_date) <= 7 THEN 1 ELSE 0 END - CASE WHEN DATEPART(dw, @last_date) < 7 THEN 1 ELSE 0 END) + (DATEDIFF(WEEK, @start_date, @last_date) + CASE WHEN DATEPART(dw, @start_date) <= 1 THEN 1 ELSE 0 END - CASE WHEN DATEPART(dw, @last_date) < 1 THEN 1 ELSE 0 END) ) AS total_fri_sat_sun;
解决方案2:生成日期序列统计(直观不易错)
生成上月所有日期的序列,再筛选出周五、周六、周日进行计数,逻辑更直观,适合复杂日期筛选场景。
DECLARE @start_date DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0); DECLARE @last_date DATE = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) - 1, -1); -- 统一设置周日为一周第一天 SET DATEFIRST 7; SELECT COUNT(*) AS total_fri_sat_sun FROM ( -- 生成上月所有日期 SELECT DATEADD(DAY, number, @start_date) AS date FROM master..spt_values WHERE type = 'P' AND DATEADD(DAY, number, @start_date) <= @last_date ) AS all_month_dates -- 筛选周五(6)、周六(7)、周日(1) WHERE DATEPART(dw, date) IN (1, 6, 7);
原代码问题说明
你之前的代码仅针对周六、周日计算,且在日期范围的处理上存在错误(比如DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) - 3, -1)的偏移逻辑不正确),同时未包含周五的统计,因此无法满足需求。
内容的提问来源于stack exchange,提问作者Frantisek veseli
相关产品推荐
相关产品推荐

