ROLLUP按列序层级递减汇总,仅生成N+1组结果;CUBE穷举2^N种组合,必多于ROLLUP;NULL需用GROUPING()区分真假;CUBE性能开销显著高于ROLLUP,尤其多列大数据量时。

ROLLUP只按列顺序“卷起”,不是所有列都参与汇总
ROLLUP 的行为本质是层级递减:它从 GROUP BY 列表最左开始,逐次去掉右侧列,直到只剩第一个列,最后全去掉。比如 GROUP BY ROLLUP(a, b, c) 实际等价于这四组 GROUP BY 的 UNION ALL:
GROUP BY a, b, cGROUP BY a, bGROUP BY a-
GROUP BY ()(全表汇总)
注意:b 和 c 单独出现的汇总行(如 NULL, b, NULL 或 NULL, NULL, c)不会产生——因为 ROLLUP 不“跳列”或“重排”,它严格依赖书写顺序。
CUBE穷举所有维度组合,2^N 是硬性数学规律
CUBE 的逻辑是把每个分组列看作一个二元开关:参与聚合 or 不参与。N 列就有 2^N 种开关状态,每种对应一行结果。例如 GROUP BY CUBE(a, b, c) 会生成全部 8 行:
a, b, ca, b, NULLa, NULL, ca, NULL, NULLNULL, b, cNULL, b, NULLNULL, NULL, cNULL, NULL, NULL
这就是为什么 CUBE 总比 ROLLUP 多出若干行——只要列数 ≥ 2,2^N 就一定大于 N+1。比如两列时:CUBE 有 4 行,ROLLUP 只有 3 行;三列时:CUBE 8 行 vs ROLLUP 4 行。
当列中真实存在 NULL 值时,GROUPING() 是唯一可靠区分手段
无论是 ROLLUP 还是 CUBE,生成的汇总行都会用 NULL 占位。但原始数据里也可能有合法的 NULL(比如某员工部门未填写)。这时仅靠 IS NULL 无法判断该 NULL 是数据缺失还是汇总标记。
必须用 GROUPING() 函数:
-
GROUPING(a) = 1→ 这行是因 ROLLUP/CUBE 生成的汇总行,a 列被“卷起”或“排除”了 -
GROUPING(a) = 0→ a 列值来自实际数据(哪怕它恰好是NULL)
典型写法:COALESCE(NULLIF(a, ''), '小计') 不够安全;应写成:CASE WHEN GROUPING(a) = 1 THEN '小计' ELSE ISNULL(a, '[未填]') END。
性能差异在多列场景下会急剧放大
ROLLUP 扫描数据 1 次,内部按排序/哈希分组即可完成 N+1 个聚合;CUBE 在多数引擎中需构建更复杂的哈希立方体或多次扫描,尤其当列基数高、行数大时:
- 2 列、百万行:CUBE 可能比 ROLLUP 慢 1.5–2 倍
- 4 列、千万行:CUBE 可能触发内存溢出或执行计划退化为嵌套循环
- Oracle/SQL Server 对 CUBE 有优化,但 PostgreSQL 直到 v14 才支持原生 CUBE,此前只能靠
UNION ALL模拟,开销更大
别只看语法简洁——上线前务必在生产数据量级上压测 GROUP BY CUBE(...) 的执行时间与资源消耗。

















