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的分区为例,排序后三行的计算逻辑如下:
- 第一行(event_date=2016-03-01):帧范围是第1行~第1行,sum(games_played) = 5
- 第二行(event_date=2016-05-02):帧范围是第1行~第2行,sum(games_played) = 5+6=11
- 第三行(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
相关产品推荐
相关产品推荐

