ROLLUP是GROUP BY的扩展操作符,非函数,按GROUP BY列从左到右前缀递减生成层级汇总:(A,B,C)→(A,B)→(A)→(),自动补全小计与总计,避免UNION漏层、对不齐及NULL误判。

ROLLUP 不是函数,是 GROUP BY 的扩展操作符 —— 用错语法或理解偏差,结果会漏汇总、多空行、甚至报错。
为什么 GROUP BY ... WITH ROLLUP 比写多个 UNION 更可靠
手工拼 UNION 各级汇总(比如部门+年份、仅部门、总计)容易漏层级、字段对不齐、NULL 值处理混乱;而 WITH ROLLUP 由数据库引擎自动补全分组层级,顺序严格按 GROUP BY 列的从左到右“前缀递减”生成:(A,B,C) → (A,B) → (A) → ()。
- MySQL 8.0+ 和 MariaDB 支持
GROUP BY ... WITH ROLLUP,但 PostgreSQL / SQL Server 用GROUPING SETS替代 - Oracle 用
ROLLUP()函数包裹列(注意括号),语法不同但语义一致 - 所有实现中,汇总行的空值字段实际是
NULL,不是字符串'NULL',别用= NULL判断,得用IS NULL
如何让财务报表中的“合计”行带可读标签(如‘总计’‘小计’)
直接 GROUP BY dept, year WITH ROLLUP 会产生一堆 NULL,用户看不懂哪行是部门小计、哪行是全局总计。必须配合 GROUPING() 或 COALESCE() 做语义标注。
SELECT COALESCE(dept, '【部门合计】') AS dept, COALESCE(CAST(year AS CHAR), '【年度合计】') AS year, SUM(revenue) AS total_revenue FROM financial_data GROUP BY dept, year WITH ROLLUP;
-
GROUPING(dept)返回 1 表示该行是 dept 维度的汇总(即 dept 为 NULL 是引擎主动补的,不是原始数据缺失) - 优先用
GROUPING()而非IS NULL,避免原始数据真含 NULL 导致误标 - 注意
CAST(year AS CHAR):year 是数字时,COALESCE(year, 'xxx')会触发隐式转换报错,必须显式转类型
遇到 “Column ‘xxx’ is not in GROUP BY” 错误怎么办
开启 sql_mode=only_full_group_by(MySQL 默认启用)后,SELECT 中所有非聚合字段必须出现在 GROUP BY 子句里 —— 但 WITH ROLLUP 会让部分字段在汇总行变 NULL,引擎仍要求它们显式声明。
- 错误写法:
SELECT dept, year, SUM(revenue) FROM t GROUP BY dept WITH ROLLUP(year 没进 GROUP BY,却出现在 SELECT) - 正确写法:
SELECT dept, year, SUM(revenue) FROM t GROUP BY dept, year WITH ROLLUP(即使你只想按 dept 汇总,year 也得写上,否则报错) - 如果 year 真不需要参与分组逻辑,就别 SELECT 它,或改用子查询先聚合再关联维度表
真正难的不是写出 WITH ROLLUP,而是厘清业务层级关系:哪些字段构成自然树状结构(如 region → province → city),哪些只是平行维度(如 channel 和 product_type)。ROLLUP 只认顺序,乱排列会导致汇总逻辑完全错位。

















