如何在同一CTE作用域内访问刚创建的列实现rn累计计算
单CTE实现方案
你需要的累计计算逻辑本质是全局按日期、时间升序排序后,对每个日期分组内生成的顺序行号做逐行累计求和,不需要递归、不需要嵌套多层CTE,直接在单个CTE的SELECT子句中嵌套窗口函数即可实现,完全符合「同一CTE作用域内完成行号生成+累计计算」的要求。
实现代码
WITH cte AS( SELECT _date, _time, SUM(ROW_NUMBER() OVER (PARTITION BY _date ORDER BY _time)) OVER (ORDER BY _date, _time ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS rn FROM @sample ) SELECT * FROM cte
逻辑说明
- 内层嵌套的
ROW_NUMBER() OVER (PARTITION BY _date ORDER BY _time)完全沿用你原有的组内行号生成规则,按日期分组、时间升序生成每组内从1开始的连续序号 - 外层的
SUM() OVER (...)窗口定义全局排序规则为日期升序、时间升序,计算从结果集第一行到当前行的所有行号总和,这个计算逻辑和你描述的「逐行遍历,当前行最终值=自身原始行号+上一行计算后的值」完全等价,SQL引擎会自动按顺序完成累计,不需要手动写递归或逐行取值逻辑。
注意:外层SUM窗口的ORDER BY规则必须和行号生成的排序规则对齐,否则会出现累计顺序错乱、结果不符合预期的问题。这种基于集合的窗口函数写法性能远高于递归迭代写法,数据量较大时优势明显。
执行结果
运行上述代码返回的结果和你给出的预期完全一致:
| _date | _time | rn |
|---|---|---|
| 2022-06-22 | 09:00:00 | 1 |
| 2022-06-22 | 09:30:00 | 3 |
| 2022-06-22 | 10:00:00 | 6 |
| 2022-06-22 | 10:30:00 | 10 |
| 2022-06-22 | 11:00:00 | 15 |
| 2022-06-23 | 09:00:00 | 16 |
| 2022-06-23 | 09:30:00 | 18 |
| 2022-06-23 | 10:00:00 | 21 |
内容的提问来源于stack exchange,提问作者Cheese
相关产品推荐
相关产品推荐

