累计求和必须用ORDER BY,否则结果不可靠;正确写法为SUM(amount) OVER(PARTITION BY user_id ORDER BY create_time ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),并注意索引、空值和重复值处理。

累计求和必须用 ORDER BY,否则结果不可靠
窗口函数如 SUM() OVER() 计算累计值时,ORDER BY 不是可选的——它定义了“累计”的顺序。没有 ORDER BY,数据库会按任意物理顺序累加,同一查询多次执行可能返回不同结果。
常见错误写法:SUM(amount) OVER (PARTITION BY user_id) —— 这只是分组内总和,不是累计值。
- 正确写法必须带排序:
SUM(amount) OVER (PARTITION BY user_id ORDER BY create_time) - 时间字段含重复值时,建议补一个唯一列(如
id)避免非确定性:ORDER BY create_time, id - 若需升序累计(最早→最新),用默认升序;降序累计(最新→最早)则显式写
ORDER BY create_time DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 是默认行为,但显式写出更安全
很多教程省略帧子句,依赖默认的 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。这在大多数场景下成立,但某些数据库(如老版本 PostgreSQL 或特定执行计划下)可能表现不一致。
MATLAB(矩阵实验室)是MATrix LABoratory的缩写,是一款由美国The MathWorks公司出品的商业数学软件。MATLAB是一种用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境。除了矩阵运算、绘制函数/数据图像等常用功能外,MATLAB还可以用来创建用户界面及与调用其它语言(包括C,C++和FORTRAN)编写的程序。MATLAB基础知识;命令窗口是用户与MATLAB进行交互作业的主要场所,用户输入的MATLAB交互命令均在命令窗口执行。 感兴趣的朋友可以
- 显式声明能杜绝歧义:
SUM(amount) OVER (PARTITION BY user_id ORDER BY create_time ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) - 不要用
RANGE帧(如RANGE BETWEEN...),它对时间/数值型排序键容易因重复值导致“跳加”,产生意外累计结果 - 如果真要跳过当前行(比如计算“截至上一行”的累计),改用
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
空值(NULL)会被自动跳过,但要注意排序字段为 NULL 的行位置
SUM() 窗口函数天然忽略 NULL 值,这点和普通聚合一致。真正容易出错的是排序字段本身为 NULL:不同数据库对 NULLS FIRST/NULLS LAST 默认处理不同。
- PostgreSQL 默认
NULLS FIRST,MySQL 8.0+ 默认NULLS LAST,结果可能错位 - 稳妥做法是显式声明:
ORDER BY create_time NULLS LAST(假设你想把有效时间排前面) - 如果业务上不允许
create_time为空,建表时应加NOT NULL约束,比运行时处理更可靠
性能敏感场景下,避免在大表上对非索引字段 ORDER BY
累计值计算本质是按序扫描,若 ORDER BY 字段无索引,数据库可能触发全表排序(External Sort),I/O 和内存开销陡增。
- 检查执行计划中是否出现
Sort节点且Rows Removed by Filter很高 - 复合索引优先考虑:
(user_id, create_time)—— 同时支撑分区与排序 - 如果只是查最近 N 条的累计(如“最近 30 天用户每日充值累计”),先用子查询或 CTE 限定数据范围,再套窗口函数,比全表扫快得多









