SQL 使用窗口函数计算累计值
发布时间 - 2026-01-24 00:00:00 点击率:次累计求和必须用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 或特定执行计划下)可能表现不一致。
- 显式声明能杜绝歧义:
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 限定数据范围,再套窗口函数,比全表扫快得多
# mysql
# sql
# NULL
# sort
# Filter
# postgresql
# 数据库
# 升序
# 跳过
# 不可靠
# 的是
# 子句
# 几天
# 半天
# 很高
# 才发现
# 这只
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
原生JS实现图片轮播切换效果
今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】
香港服务器租用每月最低只需15元?
Laravel怎么导出Excel文件_Laravel Excel插件使用教程
Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制
如何正确下载安装西数主机建站助手?
浅述节点的创建及常见功能的实现
Linux系统运维自动化项目教程_Ansible批量管理实战
黑客如何通过漏洞一步步攻陷网站服务器?
如何在阿里云服务器自主搭建网站?
高性价比服务器租赁——企业级配置与24小时运维服务
Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
php 三元运算符实例详细介绍
如何用花生壳三步快速搭建专属网站?
零基础网站服务器架设实战:轻量应用与域名解析配置指南
猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
如何在服务器上配置二级域名建站?
如何实现javascript表单验证_正则表达式有哪些实用技巧
如何用狗爹虚拟主机快速搭建网站?
Laravel如何集成Inertia.js与Vue/React?(安装配置)
Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】
Python3.6正式版新特性预览
javascript读取文本节点方法小结
如何在腾讯云服务器上快速搭建个人网站?
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
如何在不使用负向后查找的情况下匹配特定条件前的换行符
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
微信小程序 canvas开发实例及注意事项
Swift中switch语句区间和元组模式匹配
详解Android中Activity的四大启动模式实验简述
如何用西部建站助手快速创建专业网站?
如何利用DOS批处理实现定时关机操作详解
,交易猫的商品怎么发布到网站上去?
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
java中使用zxing批量生成二维码立牌
WordPress 子目录安装中正确处理脚本路径的完整指南
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
深圳网站制作的公司有哪些,dido官方网站?
简历在线制作网站免费版,如何创建个人简历?
使用spring连接及操作mongodb3.0实例
Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面
海南网站制作公司有哪些,海口网是哪家的?
黑客如何利用漏洞与弱口令入侵网站服务器?
Laravel模型关联查询教程_Laravel Eloquent一对多关联写法
详解Android图表 MPAndroidChart折线图
Laravel怎么使用Session存储数据_Laravel会话管理与自定义驱动配置【详解】
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件

