PostgreSQL中ROLLUP分组与窗口表达式结合时百分比计算异常
问题原因解析
当你在GROUP BY中加入ROLLUP(mth, dy)后,窗口函数的计算逻辑发生了关键变化,导致百分比不符合预期,核心原因是窗口函数的执行时机在ROLLUP分组之后:
无ROLLUP的场景:
原语句GROUP BY yr, mth, dy只会生成「年-月-日」级别的分组行,窗口函数SUM(COUNT(*)) OVER (PARTITION BY YEAR(evt_date), MONTH(evt_date))计算的是当月所有日级分组的count总和(也就是当月的总记录数),此时百分比是「当日count / 当月总count」,结果符合预期。加入ROLLUP后的场景:
ROLLUP(mth, dy)会生成三层分组行:- 「年-月-日」的日级行
- 「年-月」的月度汇总行(
dy为NULL) - 「年」的年度汇总行(
mth和dy均为NULL)
此时窗口函数是在ROLLUP生成的所有分组行上计算的,SUM(COUNT(*)) OVER (...)会把分区内的日级行count、月度汇总行count全部加起来。比如某月度总count是20,日级两行各10,ROLLUP后多了一行count=20的月度汇总行,窗口SUM的结果就是10+10+20=40,导致日级行的百分比变成25%,月度汇总行变成50%,完全偏离了「占当月总count比例」的预期。
简单来说,你原本期望窗口函数计算的是「原始月度总记录数」,但ROLLUP新增的汇总行被纳入了窗口求和的范围,导致分母被错误放大。
内容的提问来源于stack exchange,提问作者Guasqueño
相关产品推荐
相关产品推荐

