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

SQL Server中如何按指定条件合并连续数据行?

合并SQL Server中Department表的连续部门记录

原始表结构与数据

SQL Server中有一张名为Department的表,包含4列,数据如下:

staffNumberdepartmentstartDateendDate
100A2016-09-22 18:30:00.0002020-02-06 18:29:00.000
100B2020-02-06 18:30:00.0002022-08-21 18:29:00.000
100A2022-08-21 18:30:00.0002079-12-31 18:29:00.000
101A2018-06-03 18:30:00.0002023-08-20 18:29:00.000
101B2023-08-20 18:30:00.0002079-12-31 18:29:00.000
102A2022-12-21 18:30:00.0002023-12-29 18:29:00.000
102A2023-12-29 18:30:00.0002079-12-31 18:29:00.000
103A2016-06-22 18:30:00.0002018-03-05 18:29:00.000
103A2018-03-05 18:30:00.0002021-03-05 18:29:00.000
103A2021-03-05 18:30:00.0002079-12-31 18:29:00.000
104A2016-06-22 18:30:00.0002021-03-05 18:29:00.000
104A2021-03-05 18:30:00.0002079-12-31 18:29:00.000
105B2016-08-22 18:30:00.0002021-02-07 18:29:00.000
105B2021-02-09 18:30:00.0002079-12-31 18:29:00.000

合并条件

需要按以下规则合并多行记录:

  • 相同的staffNumber
  • 相同的department
  • 连续记录中当前行的endDate与下一行的startDate天数差为0

尝试的SQL及问题

我尝试了以下SQL查询,但未得到预期输出:

WITH DeptData_CTE AS 
(
    SELECT 
        staffNumber,
        department,
        startDate,
        endDate,
        LEAD(startDate) OVER (PARTITION BY staffNumber, department ORDER BY startDate) AS nextstartDate,
        LAG(endDate) OVER (PARTITION BY staffNumber, department ORDER BY startDate) AS prevendDate
    FROM 
        department
),
MergedData_CTE AS 
(
    SELECT 
        staffNumber,
        department,
        MIN(startDate) AS startDate,
        MAX(endDate) AS endDate
    FROM 
        DeptData_CTE
    -- We merge rows where previous expiry date and current effective date are consecutive
    WHERE 
        prevendDate IS NULL 
        OR DATEDIFF(day, prevendDate, startDate) != 0
    GROUP BY 
        staffNumber, 
        department
)
-- Final selection of rows
SELECT 
    staffNumber,
    department,
    startDate,
    endDate
FROM 
    MergedData_CTE
ORDER BY 
    staffNumber, 
    department, 
    startDate;

得到的合并行startDate符合预期,但endDate不符合——原查询直接按staffNumber和department分组,会把同一员工同一部门的所有记录(即使中间有断开)都合并成一条,比如员工100的A部门有两段时间,原查询会错误合并。

预期输出

正确的合并结果应该是:

staffNumberdepartmentstartDateendDate
100A2016-09-22 18:30:00.0002020-02-06 18:29:00.000
100B2020-02-06 18:30:00.0002022-08-21 18:29:00.000
100A2022-08-21 18:30:00.0002079-12-31 18:29:00.000
101A2018-06-03 18:30:00.0002023-08-20 18:29:00.000
101B2023-08-20 18:30:00.0002079-12-31 18:29:00.000
102A2022-12-21 18:30:00.0002079-12-31 18:29:00.000
103A2016-06-22 18:30:00.0002079-12-31 18:29:00.000
104A2016-06-22 18:30:00.0002079-12-31 18:29:00.000
105B2016-08-22 18:30:00.0002021-02-07 18:29:00.000
105B2021-02-09 18:30:00.0002079-12-31 18:29:00.000

注:员工105的两条B部门记录日期差为1天,所以不合并。

解决方案SQL

可以通过生成连续分组标识来实现正确合并,具体如下:

WITH DeptGroups AS (
    SELECT 
        staffNumber,
        department,
        startDate,
        endDate,
        -- 生成分组ID:当前记录与前一条不连续时,组号+1
        SUM(CASE 
            WHEN LAG(endDate) OVER (PARTITION BY staffNumber, department ORDER BY startDate) IS NULL 
                OR DATEDIFF(day, LAG(endDate) OVER (PARTITION BY staffNumber, department ORDER BY startDate), startDate) != 0
            THEN 1 
            ELSE 0 
        END) OVER (PARTITION BY staffNumber, department ORDER BY startDate) AS GroupId
    FROM Department
)
SELECT 
    staffNumber,
    department,
    MIN(startDate) AS startDate,
    MAX(endDate) AS endDate
FROM DeptGroups
GROUP BY staffNumber, department, GroupId
ORDER BY staffNumber, department, startDate;

逻辑说明

  1. 用LAG窗口函数获取当前记录的上一条同员工同部门记录的endDate
  2. 判断当前记录与上一条是否连续(天数差为0),不连续则生成新的分组ID
  3. 按staffNumber、department和GroupId分组,取每组的最小startDate和最大endDate,得到正确的合并结果

内容的提问来源于stack exchange,提问作者Hello World

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:35:54