SQL Server中如何使用DATEDIFF函数排除周末?
嘿,刚学SQL完全不用不好意思,谁都是从新手阶段过来的!针对你想排除周末计算平均工作日天数的需求,我给你整理了几种实用的方案,你可以根据自己用的SQL数据库来选~
核心思路
不管用哪种方法,本质都是先算出时间段内的总天数,再减去这段时间里周六和周日的数量,最后求平均值。
方案1:用公式直接计算(性能最优,适合大数据量)
这种方法不用循环,靠日期函数计算周末数量,速度很快。以SQL Server为例:
SELECT AVG(1.00 * ( -- 计算总天数(包含起始和结束日期) DATEDIFF(day, start_date, end_date) + 1 -- 减去这段时间里的周六数量 - (DATEDIFF(week, start_date, end_date) + CASE WHEN DATEPART(weekday, start_date) = 7 THEN 1 ELSE 0 END) -- 减去这段时间里的周日数量 - (DATEDIFF(week, start_date, end_date) + CASE WHEN DATEPART(weekday, end_date) = 1 THEN 1 ELSE 0 END) )) AS avg_working_days FROM your_table;
代码解释:
DATEDIFF(week, start_date, end_date):返回两个日期之间的完整周数,每个完整周固定有1个周六和1个周日。- 额外的
CASE语句:用来补全不完整周的周末——如果起始日是周六,要多减1天;如果结束日是周日,也要多减1天。 - 注意:不同数据库的
weekday返回值可能不同!比如有的数据库1代表周一,7代表周日,你可以先运行SELECT DATEPART(weekday, GETDATE())(SQL Server)测试一下,再调整CASE里的数值。
方案2:自定义工作日计算函数(复用性强,适合小数据量)
如果你经常需要计算工作日,可以写一个自定义函数,之后直接调用就行:
-- 先创建函数(SQL Server为例) CREATE FUNCTION dbo.GetWorkingDays(@StartDate DATE, @EndDate DATE) RETURNS INT AS BEGIN DECLARE @WorkDays INT = 0; WHILE @StartDate <= @EndDate BEGIN -- 排除周六(7)和周日(1),根据你的数据库调整数值 IF DATEPART(weekday, @StartDate) NOT IN (1,7) SET @WorkDays = @WorkDays + 1; SET @StartDate = DATEADD(day, 1, @StartDate); END RETURN @WorkDays; END;
然后查询时直接调用:
SELECT AVG(1.00 * dbo.GetWorkingDays(start_date, end_date)) AS avg_working_days FROM your_table;
⚠️ 注意:循环方法如果处理几十万条以上的数据,性能会比公式法差一些,小数据量用着很方便。
其他数据库的小调整
- MySQL:用
DAYOFWEEK()函数(1=周日,7=周六),计算逻辑类似:
SELECT AVG(1.00 * ( DATEDIFF(end_date, start_date) + 1 - FLOOR((DATEDIFF(end_date, start_date) + DAYOFWEEK(start_date)) / 7) - FLOOR((DATEDIFF(end_date, start_date) + (8 - DAYOFWEEK(start_date))) / 7) )) AS avg_working_days FROM your_table;
- PostgreSQL:用
EXTRACT(DOW FROM date)(0=周日,6=周六),可以生成日期序列来统计周末:
SELECT AVG(1.00 * ( (end_date - start_date + INTERVAL '1 day')::INT - (SELECT COUNT(*) FROM generate_series(start_date, end_date, INTERVAL '1 day') AS d WHERE EXTRACT(DOW FROM d) IN (0,6)) )) AS avg_working_days FROM your_table;
内容的提问来源于stack exchange,提问作者Pat
相关产品推荐
相关产品推荐

