如何为订单中连续时段的手动输入DueDate分配分组编号?
解决订单连续相同DueDate时段分组编号问题
需求说明
某订单系统通过唯一的SysLogDate(实际为datetime,此处简化为date)跟踪手动输入的DueDate,需要为每个订单内按时间顺序连续、未变更的DueDate时段分配独立分组编号。举个例子:先设置4/10为DueDate,之后改为4/15,再改回4/10,这三个时段要分成3个独立分组,方便后续分析截止日期变更原因。
原方案问题
你尝试用DENSE_RANK()编写的脚本会把同一订单内所有相同的DueDate归为同一组,无法区分非连续的相同时段,导致分组错误。原脚本如下:
Select *, Dense_Rank() OVER (Partition By OrderNo, DueDate Order By SysLogDate) as SectionNumber_WithinDueDate From #DueDates
正确实现方案
这里可以用差值分组法,通过标记DueDate的变更点,再累计变更次数生成分组编号:
方法一(带CTE,逻辑清晰)
WITH RankedDates AS ( SELECT *, -- 标记当前记录与上一条DueDate是否发生变更 CASE WHEN LAG(DueDate) OVER (PARTITION BY OrderNo ORDER BY SysLogDate) = DueDate THEN 0 ELSE 1 END AS IsChange FROM #DueDates ) SELECT *, -- 累计变更次数,得到连续相同DueDate的分组编号 SUM(IsChange) OVER (PARTITION BY OrderNo ORDER BY SysLogDate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SectionNumber_WithinDueDate FROM RankedDates ORDER BY OrderNo, SysLogDate;
方法二(简化版,无需CTE)
SELECT *, SUM( CASE WHEN LAG(DueDate) OVER (PARTITION BY OrderNo ORDER BY SysLogDate) = DueDate THEN 0 ELSE 1 END ) OVER (PARTITION BY OrderNo ORDER BY SysLogDate ROWS UNBOUNDED PRECEDING) AS SectionNumber_WithinDueDate FROM #DueDates ORDER BY OrderNo, SysLogDate;
原理说明
- 用
LAG()函数获取同一订单中当前记录的上一条DueDate,对比当前DueDate:如果两者相同,说明属于同一连续时段,标记为0;如果不同,说明是新时段的开始,标记为1。 - 对每个订单,按
SysLogDate顺序累计IsChange的值——每遇到一次变更(标记为1),累计值就加1,这样就能为每个连续相同的DueDate时段分配唯一的分组编号。
内容的提问来源于stack exchange,提问作者jn4248
相关产品推荐
相关产品推荐

