Oracle SQL:仅当日期存在间隔时递增分组编号
问题描述
原始数据:
| ID | 开始日期 | 结束日期 |
|---|---|---|
| 1 | 1/1/2023 | 2/1/2023 |
| 1 | 2/2/2023 | 2/15/2023 |
| 1 | 2/20/2023 | 9/21/2023 |
| 1 | 9/22/2023 | 10/11/2023 |
| 2 | 1/11/2023 | 4/11/2023 |
| 2 | 5/9/2023 | 6/15/2023 |
| 2 | 7/7/2023 | 9/17/2023 |
需求:按ID分区,同一ID组内,仅当上一行结束日期与当前行开始日期存在间隔(即当前开始日期晚于上一行结束日期+1天)时,分组编号递增,否则保持同一分组。期望结果:
| ID | 开始日期 | 结束日期 | 分组 |
|---|---|---|---|
| 1 | 1/1/2023 | 2/1/2023 | 1 |
| 1 | 2/2/2023 | 2/15/2023 | 1 |
| 1 | 2/20/2023 | 9/21/2023 | 2 |
| 1 | 9/22/2023 | 10/11/2023 | 2 |
| 2 | 1/11/2023 | 4/11/2023 | 1 |
| 2 | 5/9/2023 | 6/15/2023 | 2 |
| 2 | 7/7/2023 | 9/17/2023 | 3 |
解决方案(Oracle SQL)
通过LAG()窗口函数获取上一行的结束日期,结合条件判断生成间隔标识,再用SUM()窗口函数累计标识值得到分组编号:
WITH date_gaps AS ( SELECT ID, 开始日期, 结束日期, -- 标记当前行是否与上一行存在间隔:当前开始日期 > 上一行结束日期+1天则标记为1,否则0 CASE WHEN LAG(结束日期) OVER (PARTITION BY ID ORDER BY 开始日期) + 1 < 开始日期 THEN 1 ELSE 0 END AS gap_flag FROM your_table_name ) SELECT ID, 开始日期, 结束日期, -- 累计gap_flag值,+1后得到从1开始的分组编号 SUM(gap_flag) OVER (PARTITION BY ID ORDER BY 开始日期) + 1 AS 分组 FROM date_gaps ORDER BY ID, 开始日期;
逻辑说明
- LAG()函数:按ID分区、开始日期排序,获取当前行的上一行结束日期,用于间隔判断。
- gap_flag标记:第一行无前置行,gap_flag默认为0;后续行若与上一行日期存在间隔则标记为1,否则0。
- SUM()窗口累计:按ID分区、开始日期排序,累计gap_flag的值,加1后得到连续分组编号——每次遇到间隔,累计值加1,分组编号递增;无间隔时累计值不变,分组编号保持一致。
注意:若日期字段为字符串类型,需先用TO_DATE(日期字段, 'MM/DD/YYYY')转换为DATE类型,否则日期比较会出错。
内容的提问来源于stack exchange,提问作者ra_learns
相关产品推荐
相关产品推荐

