You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:通用自定义计算逻辑(适配所有数据库)

如果你的数据库没有内置工作日函数,可以用以下通用逻辑计算:

  1. 计算两个日期之间的总天数
  2. 减去这段时间内的整周周末天数(每周2天)
  3. 调整首尾日期的周末情况(如果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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:53:49