You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL sum() over(partition by order by)窗口函数累计求和原理疑问

窗口函数执行逻辑说明

你观察到的逐行累加效果,核心是带ORDER BY的聚合类窗口函数默认启用了滚动累积窗口帧(Frame)规则,和你预期的「分组后全组聚合」的差异就出在窗口帧的默认配置上,完整执行逻辑拆分如下:

第一步:分区(PARTITION BY 逻辑)

和你的理解一致,SQL会先按partition by player_id将整张Activity表拆分为独立分区:

  • 分区1:所有player_id=1的行
  • 分区2:所有player_id=3的行
    不同分区的计算完全独立,互不干扰。

第二步:分区内排序+默认帧规则生效

order by event_date除了会将分区内的行按日期升序排列外,对于SUM、COUNT这类聚合窗口函数,只要在OVER子句中指定了ORDER BY,就会自动添加默认窗口帧限制:

RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

翻译为:计算范围是「当前分区的第一行,一直到当前行」。

第三步:逐行计算累计值

以player_id=1的分区为例,排序后三行的计算逻辑如下:

  1. 第一行(event_date=2016-03-01):帧范围是第1行~第1行,sum(games_played) = 5
  2. 第二行(event_date=2016-05-02):帧范围是第1行~第2行,sum(games_played) = 5+6=11
  3. 第三行(event_date=2017-06-25):帧范围是第1行~第3行,sum(games_played) =5+6+1=12
    刚好对应你得到的逐行累计结果。

扩展:如果要获取全分区总和的写法

如果你想要的是「同一玩家所有行返回该玩家的总游戏数」而非累计值,可以手动指定帧范围为全分区,写法如下:

sum(games_played) over(
  partition by player_id 
  range between unbounded preceding and unbounded following
) as total_games

或者直接去掉OVER子句中的ORDER BY,也会默认计算全分区总和。

内容的提问来源于stack exchange,提问作者user_12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:15:03