如何合并同一A_ID下时间无间断的起止日期?已尝试多种方法未成功
合并同一A_ID下连续时间段的SQL解决方案
嘿,我明白你要解决的问题——把同一A_ID下时间无缝衔接的起止日期合并成一个连续区间对吧?这是典型的区间合并场景,咱们一步步来搞定它。
首先先确认你的测试数据:
CREATE TABLE #t ( A_ID VARCHAR(100), BDate VARCHAR(100), CDate VARCHAR(100) ) INSERT INTO #t (A_ID, BDate, CDate) VALUES ('1000','2017/12/01','2017/12/31'), ('1000','2018/01/01','2018/03/31'), ('1000','2018/05/01','2018/05/31')
你的思路用窗口函数是对的,但需要进一步区分哪些行属于同一个连续区间。这里我们可以用LAG函数对比当前行的起始日期和上一行的结束日期,判断是否连续,再生成分组标识来聚合。
完整解决方案代码
WITH date_converted AS ( -- 先把字符串日期转换成DATE类型,方便日期运算 SELECT A_ID, CONVERT(DATE, BDate, 111) AS BDate, CONVERT(DATE, CDate, 111) AS CDate FROM #t ), interval_groups AS ( -- 标记每个连续区间的起始点,生成分组ID SELECT A_ID, BDate, CDate, -- 如果当前行的BDate是上一行CDate的下一天,属于同一组;否则新组 SUM(CASE WHEN LAG(CDate) OVER (PARTITION BY A_ID ORDER BY BDate) = DATEADD(DAY, -1, BDate) THEN 0 ELSE 1 END) OVER (PARTITION BY A_ID ORDER BY BDate) AS GroupID FROM date_converted ) -- 按A_ID和GroupID聚合,取每个组的最小起始日期和最大结束日期 SELECT A_ID, CONVERT(VARCHAR(100), MIN(BDate), 111) AS Merged_BDate, CONVERT(VARCHAR(100), MAX(CDate), 111) AS Merged_CDate FROM interval_groups GROUP BY A_ID, GroupID ORDER BY A_ID, Merged_BDate;
代码解释
- date_converted CTE:把
VARCHAR类型的日期转换成DATE类型,这样才能正确进行日期加减和比较操作(建议实际业务表直接用DATE类型存日期,避免字符串格式问题)。 - interval_groups CTE:使用
LAG(CDate) OVER (PARTITION BY A_ID ORDER BY BDate)获取同一A_ID下上一行的结束日期,判断当前行的起始日期是否是上一行结束日期的下一天——如果是,说明两个区间连续,属于同一组;否则是新的组。用SUM累加标记值生成唯一的GroupID。 - 最后聚合步骤:按
A_ID和GroupID分组,取每个组的最小起始日期和最大结束日期,就是合并后的连续区间。
预期输出
| A_ID | Merged_BDate | Merged_CDate |
|---|---|---|
| 1000 | 2017/12/01 | 2018/03/31 |
| 1000 | 2018/05/01 | 2018/05/31 |
这样就完美合并了连续的时间段,不连续的区间也能保持独立~
内容的提问来源于stack exchange,提问作者Dave17003
相关产品推荐
相关产品推荐

