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

SQL如何基于公共假日为员工连续休假记录正确分组

员工休假表按公共假日分组SQL实现

基础样例数据

员工休假表Emp_Vacation样例数据如下:

Emp_id   Vacation_Start_Date    Vacation_End_Date Public_Hday
1234         06/01/2022            06/07/2022       null
1234         06/08/2022            06/14/2022       null
1234         06/15/2022            06/19/2022       06/17/2022
1234         06/20/2022            06/23/2022       null
1234         06/24/2022            06/28/2022       null
1234         06/29/2022            07/02/2022       06/30/2022
1234         07/03/2022            07/07/2022       null
1234         07/08/2022            07/12/2022       null
1234         07/13/2022            07/17/2022       07/15/2022
1234         07/18/2022            07/22/2022       null

分组需求

已知所有休假记录时间连续,需要根据休假区间内的公共假日对记录分组,预期输出如下:

Emp_id   Vacation_Start_Date    Vacation_End_Date  Public_Hday    Group
    1234         06/01/2022            06/07/2022       null           0
    1234         06/08/2022            06/14/2022       null           0
    1234         06/15/2022            06/19/2022       06/17/2022     1
    1234         06/20/2022            06/23/2022       null           1 
    1234         06/24/2022            06/28/2022       null           1
    1234         06/29/2022            07/02/2022       06/30/2022     2
    1234         07/03/2022            07/07/2022       null           2
    1234         07/08/2022            07/12/2022       null           2
    1234         07/13/2022            07/17/2022       07/15/2022     3
    1234         07/18/2022            07/22/2022       null           3

原有写法问题

已尝试的SQL如下:

Select *, dense_rank() over (partition by Emp_id order by Public_Hday) - 1 AS Group from Emp_Vacation;

该写法的问题是:dense_rank按Public_Hday排序时,所有null值会被归为同一排序秩,无法区分不同公共假日区间前后的空值记录,只有Public_Hday非空的记录能返回正确组号。

正确实现方案

分组逻辑本质是:按休假时间顺序排列后,每遇到1条带公共假日的记录,组号加1,公共假日之后直到下一个公共假日出现前的所有记录,和当前公共假日记录同组,第一条公共假日之前的记录归为组0。
利用COUNT聚合窗口函数会自动忽略null值的特性,统计截止到当前行(按休假开始时间排序),该员工累计出现的非空公共假日数量,即可直接得到目标组号,SQL写法如下:

SELECT 
    *,
    COUNT(Public_Hday) OVER (
        PARTITION BY Emp_id 
        ORDER BY Vacation_Start_Date
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS `Group`
FROM Emp_Vacation;

注:显式指定窗口帧范围是为了兼容不同数据库的默认窗口规则,避免结果异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:28:03