首页/数据/SQL 速查/ROLLUP 分组小计与合计
聚合与窗口函数54 条

ROLLUP 分组小计与合计

GROUP BY ... WITH ROLLUP 在结果中追加小计与总计行:MySQL 8 与 PostgreSQL 均支持,小计行的分组列显示为 NULL。

SQL 速查数据更新于 2026-10-13

ROLLUP 是什么

ROLLUP 在普通分组的基础上额外产出小计与总计行:按 a、b 分组时,结果里会同时出现每个 a 下的明细行、每个 a 的小计行(b 显示为 NULL),以及整表合计行(a、b 都为 NULL)。MySQL 8 用 GROUP BY a, b WITH ROLLUP,PostgreSQL 9.5+ 用标准写法 GROUP BY ROLLUP(a, b)。风险点在于区分「小计行」与「真实的 NULL 分组」:两者外观相同,必须用 GROUPING() 判断,否则口径会乱。

基本信息

适用平台MySQL 8.0(WITH ROLLUP 或 ROLLUP(...))、PostgreSQL 9.5+
MySQL 写法GROUP BY 列… WITH ROLLUP,或 GROUP BY ROLLUP(列…)
PostgreSQL 写法GROUP BY ROLLUP (列…)
层级判定GROUPING() 返回 1 表示该列由聚合上卷而来,MySQL 按列分别调用
排序建议把 GROUPING() 结果放进 ORDER BY,让明细行在前、小计合计在后

典型使用场景

  • 报表输出小计与合计,避免手工累加或多次查询
  • 按地区与渠道两级汇总销售额
  • 多级维度逐层上卷,一次查询拿到所有层级
  • 与 GROUPING() 配合标记每一行的层级,前端据此缩进展示
  • 替代多次 UNION ALL 拼装的分层统计,写法更短且口径统一

MySQL 写法

MySQL 写法
SELECT COALESCE(region, '全部')  AS region,
       COALESCE(channel, '小计') AS channel,
       SUM(amount)               AS total,
       GROUPING(region)          AS g_region,    # 1 表示该列是上卷小计
       GROUPING(channel)         AS g_channel
FROM orders
GROUP BY region, channel WITH ROLLUP
ORDER BY g_region, region, g_channel;

PostgreSQL 写法

PostgreSQL 写法
-- 标准写法,括号里是上卷顺序:先 channel,再 region
SELECT COALESCE(region, '全部')  AS region,
       COALESCE(channel, '小计') AS channel,
       SUM(amount)               AS total,
       GROUPING(region, channel) AS grp          -- 多参数返回位掩码
FROM orders
GROUP BY ROLLUP (region, channel)
ORDER BY grp, region, channel;

层级判定与排序

判定结果含义处理建议
GROUPING 为 0该列参与分组,是明细行正常展示列值
GROUPING 为 1(某一列)该列为上卷产生的小计/合计行显示「小计」「全部」等标签
多列 ROLLUP按括号内顺序自右向左逐层上卷排序列顺序与 ROLLUP 保持一致
真实 NULL 分组与小计行外观相同必须用 GROUPING() 区分,不能靠 IS NULL
把 GROUPING() 的返回值参与排序,就能自然得到「明细在前、小计居中、合计在最后」的层次结构;只按列值排序会把小计行的 NULL 排到最前面。
真实 NULL 分组与 ROLLUP 生成的小计行在结果里长得一样:直接对分组列做 COALESCE 会把真实空值也标成「小计」,必须用 GROUPING() 区分层级后再做展示处理。
ROLLUP 是 GROUPING SETS 的特例:它只按列顺序逐层上卷(a,b 组合、a 单独、全表),不会生成所有维度组合;需要「每个维度各自的小计」这类交叉统计时要用 CUBE 或 GROUPING SETS。

易错点

  • 把小计行的 NULL 当成真实空值处理,指标口径混乱
  • 忘记用 GROUPING() 区分层级,COALESCE 顺带改掉了真实空值
  • ROLLUP 结果不排序,小计行与合计行混在明细中间难以阅读
  • 大表上叠加多列 ROLLUP 未评估开销,结果集与中间结果明显变大

数据来源与参考

  • MySQL 8.0 Reference Manual · GROUP BY Modifiers · WITH ROLLUP
  • PostgreSQL Documentation · GROUP BY · ROLLUP
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌