SQL Server:计算当前行与上一行日期的工作日天数差值
计算行间工作日差值的解决方案
嘿,我来帮你搞定这个行间工作日计算的问题!从你给出的示例数据来看,我们需要新增NewDate和DaysDifference两列,其中NewDate取上一行的EndDate(首行无前置则为NULL,如果上一行EndDate为空则用当前行StartDate补全),DaysDifference是当前行StartDate与NewDate之间的工作日天数(仅统计周一到周五,排除周末)。
第一步:生成NewDate列
我们可以用窗口函数LAG()来获取上一行的EndDate,同时处理上一行EndDate为空的特殊情况:
WITH DateCTE AS ( SELECT ID, StartDate, EndDate, -- 获取上一行的EndDate,若为空则用当前行的StartDate补全 COALESCE(LAG(EndDate) OVER (ORDER BY ID), StartDate) AS NewDate FROM your_table_name )
第二步:计算工作日差值DaysDifference
不同数据库有不同的内置工作日计算工具,这里提供两种适配性不同的方案:
方案1:用数据库内置函数(推荐)
- SQL Server 2022+:可以直接用
DATEDIFF_BIG指定工作日范围:SELECT ID, StartDate, EndDate, NewDate, CASE WHEN NewDate IS NULL THEN NULL ELSE DATEDIFF_BIG(weekday, NewDate, StartDate, 1, 5) -- 1=周一,5=周五,定义工作日区间 END AS DaysDifference FROM DateCTE ORDER BY ID; - MySQL:通过计算总天数减去周末天数实现:
SELECT ID, StartDate, EndDate, NewDate, CASE WHEN NewDate IS NULL THEN NULL ELSE TIMESTAMPDIFF(DAY, NewDate, StartDate) - FLOOR(TIMESTAMPDIFF(DAY, NewDate, StartDate)/7)*2 - CASE WHEN WEEKDAY(NewDate) = 6 THEN 1 ELSE 0 END -- 减去NewDate是周日的情况 - CASE WHEN WEEKDAY(StartDate) = 5 THEN 1 ELSE 0 END -- 减去StartDate是周六的情况 END AS DaysDifference FROM DateCTE ORDER BY ID; - Excel/Google Sheets:如果是处理表格数据,直接用内置的
NETWORKDAYS函数更简单:# NewDate列(假设A列为ID,D列为EndDate) =IF(A2=1, "", INDEX(D:D, A2-1)) # DaysDifference列(假设B列为StartDate,E列为NewDate) =IF(E2="", "", NETWORKDAYS(E2, B2))
方案2:通用自定义计算逻辑(适配所有数据库)
如果你的数据库没有内置工作日函数,可以用以下通用逻辑计算:
- 计算两个日期之间的总天数
- 减去这段时间内的整周周末天数(每周2天)
- 调整首尾日期的周末情况(如果
NewDate是周日,或者StartDate是周六,额外减1)
完整SQL查询:
WITH DateCTE AS ( SELECT ID, StartDate, EndDate, COALESCE(LAG(EndDate) OVER (ORDER BY ID), StartDate) AS NewDate FROM your_table_name ) SELECT ID, StartDate, EndDate, NewDate, CASE WHEN NewDate IS NULL THEN NULL ELSE -- 计算总天数 DATEDIFF(day, NewDate, StartDate) -- 减去整周的周末天数 - (DATEDIFF(week, NewDate, StartDate) * 2) -- 减去NewDate是周日的情况 - CASE WHEN DATEPART(weekday, NewDate) = 1 THEN 1 ELSE 0 END -- 减去StartDate是周六的情况 - CASE WHEN DATEPART(weekday, StartDate) = 7 THEN 1 ELSE 0 END END AS DaysDifference FROM DateCTE ORDER BY ID;
匹配示例数据验证
拿你给出的示例来看:
- ID=1的
NewDate因上一行EndDate为NULL,自动补全为自身StartDate,DaysDifference是04/05/2017到12/06/2017的工作日,用NETWORKDAYS计算正好是29,和示例一致。 - ID=2的
NewDate是ID=1的EndDate(16/06/2017),StartDate是03/07/2017,工作日差值为13,和示例完全匹配。
内容的提问来源于stack exchange,提问作者Pizza
相关产品推荐
相关产品推荐

