SQL 中如何计算分组移动平均值?
时间:2026-08-25 | 作者:穿越地图的猫 | 阅读:0在MySQL 8.0+中,A VG()与OVER()搭配是计算移动平均的不二之选。其中,需通过PARTITION BY进行分组,ORDER BY实现排序,以及ROWS BETWEEN 2 PRECEDING AND CURRENT ROW来精准把控窗口范围。要注意的是,MySQL不支持RANGE时间偏移,所以对于“过去7天”的情况,需要额外处理。
MySQL 8.0+ 用 A VG() 配合 OVER() 窗口函数最直接
MySQL 5.7 及更早版本不支持窗口函数,强行用子查询或自连接算移动平均容易超时或出错;8.0+ 版本里,A VG() + OVER() 是唯一合理选择。关键不是“能不能算”,而是“怎么定义窗口范围”。
比如按时间排序、对每个用户计算最近 3 条记录的销售额移动平均:
SELECT user_id, sale_date, amount, A VG(amount) OVER ( PARTITION BY user_id ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) AS moving_a vg_3 FROM sales;
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW表示包含当前行和它前面 2 行(共 3 行),不是“过去 3 天”PARTITION BY user_id必须加,否则不同用户的记录会混在一起算- 如果
sale_date有重复,ORDER BY里要加唯一字段(如id)避免非确定性排序
PostgreSQL 和 SQL Server 的语法几乎一致,但要注意 ROWS 和 RANGE 的区别
需注意,ROWS 是按物理行数截取,而 RANGE 则是按排序值范围截取——这可是最容易出错的地方哦。就比如说,在PostgreSQL中,使用 RANGE BETWEEN INTERVAL '2 days' PRECEDING AND CURRENT ROW 是可行的,但在MySQL 8.0+ 中,却不支持 RANGE 搭配时间间隔使用。
- 想算“过去 7 天内”的移动平均,MySQL 必须先生成日期序列或用自连接,不能靠
RANGE - PostgreSQL 支持
RANGE+INTERVAL,但性能通常比ROWS差,尤其数据量大时 - SQL Server 2012+ 支持
ROWS,但不支持RANGE时间偏移,和 MySQL 一样受限
SQLite 不原生支持窗口函数,得用相关子查询硬扛
SQLite 3.25+ 虽然支持窗口函数,但很多生产环境仍在用旧版本(如 Android 系统自带 SQLite)。此时只能用相关子查询,但必须小心性能和边界行为:
SELECT t1.user_id, t1.sale_date, t1.amount, (SELECT A VG(t2.amount) FROM sales t2 WHERE t2.user_id = t1.user_id AND t2.sale_date <= t1.sale_date AND t2.sale_date >= ( SELECT MAX(t3.sale_date) FROM sales t3 WHERE t3.user_id = t1.user_id AND t3.sale_date <= t1.sale_date ORDER BY t3.sale_date DESC LIMIT 1 OFFSET 2 ) ) AS moving_a vg_3 FROM sales t1;
- 这个写法在 SQLite 中能跑,但每行都触发两次子查询,10 万行数据可能秒变秒级延迟
LIMIT 1 OFFSET 2是为了找“往前数第 3 天”,但若某用户数据稀疏(比如隔周才一条),结果会错- 没有
PARTITION BY的等价机制,WHERE条件必须手动对齐分组字段
NULL 值和首尾几行的处理逻辑必须显式确认
所有数据库对窗口开头不足 N 行的情况,都默认只算实际存在的行(即前两行的移动平均是 1 行或 2 行的均值),不会补 NULL 或 0。但如果你业务要求“不满 3 行就返回 NULL”,就得自己加判断:
- MySQL 可用
COUNT(*) OVER(...)配合CASE过滤:CASE WHEN COUNT(*) OVER(...) < 3 THEN NULL ELSE A VG(...) OVER(...) END - 首行的移动平均值等于它自己,这不是 bug,是定义如此;但报表里常被误认为异常,需提前和业务方对齐
- 如果原始数据本身含
NULL的amount,A VG()会自动忽略它们——这点和聚合函数一致,但容易被忽略
移动平均本身不难,难的是窗口定义是否贴合业务场景、数据库版本是否兜底、以及 NULL 和边界值是否符合预期。别光看结果数字对不对,先盯住那行 ROWS BETWEEN ... 有没有写错。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
