基于日期范围压缩数据:合并连续区间的Vbeln关联数据
解决连续日期区间压缩问题(SQL Server)
这是个很常见的状态区间合并需求——我们需要把同一个Vbeln下,状态(PernrZa+PernrZb)相同且日期无缝连续的多个小区间,合并成一个完整的大区间。在SQL Server里,用窗口函数就能高效实现这个需求,下面是具体的解决方案:
核心思路
- 先把字符串类型的日期转换成
datetime2,避免字符串比较的误差,方便日期运算; - 用
LAG窗口函数获取上一行的结束日期和状态,判断当前行是否和上一行属于同一个连续状态组; - 通过累计求和生成分组ID,把连续相同状态的行归为一组;
- 最后按分组聚合,得到合并后的最小开始日期和最大结束日期。
完整SQL代码
-- 第一步:转换日期格式并预处理数据 WITH ConvertedData AS ( SELECT Vbeln, -- 这里假设日期格式为YYYY.MM.DD,可根据实际格式调整CONVERT的第三个参数(比如101是MM/DD/YYYY) CONVERT(datetime2, Begda, 102) AS Begda, CONVERT(datetime2, Endda, 102) AS Endda, PernrZa, PernrZb FROM #Data ), -- 第二步:为连续相同状态的行生成分组ID GroupedData AS ( SELECT *, -- 当行与上一行状态相同且日期无缝连续时,分组ID不变;否则新建分组 SUM(CASE WHEN LAG(PernrZa) OVER (PARTITION BY Vbeln ORDER BY Begda) = PernrZa AND LAG(PernrZb) OVER (PARTITION BY Vbeln ORDER BY Begda) = PernrZb AND DATEADD(DAY, 1, LAG(Endda) OVER (PARTITION BY Vbeln ORDER BY Begda)) = Begda THEN 0 ELSE 1 END) OVER (PARTITION BY Vbeln ORDER BY Begda) AS GroupId FROM ConvertedData ) -- 第三步:按分组聚合,得到压缩后的区间 SELECT Vbeln, -- 转回字符串格式,可根据需求调整输出格式(比如'yyyyMMdd') FORMAT(MIN(Begda), 'yyyy-MM-dd') AS Begda, FORMAT(MAX(Endda), 'yyyy-MM-dd') AS Endda, PernrZa, PernrZb FROM GroupedData GROUP BY Vbeln, GroupId, PernrZa, PernrZb ORDER BY Vbeln, Begda;
关键细节说明
- 日期转换参数:如果你的
Begda和Endda不是YYYY.MM.DD格式,需要修改CONVERT函数的第三个参数,比如101对应MM/DD/YYYY,103对应DD/MM/YYYY,具体可参考SQL Server的日期转换规则; - 连续判断逻辑:这里假设日期区间是无缝衔接的(比如上一个区间的
Endda是2023-12-31,下一个的Begda是2024-01-01),如果你的连续定义是重叠或包含,需要调整DATEADD的判断条件; - 状态匹配:我们同时比较
PernrZa和PernrZb,只有两者都相同时才会合并区间,完全匹配你描述的“不同区间状态变化/恢复”的场景。
内容的提问来源于stack exchange,提问作者EnnSpace
相关产品推荐
相关产品推荐

