当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL WITH ROLLUP 怎样生成小计和总计

MySQL WITH ROLLUP 怎样生成小计和总计

来源:17golang原创 2026-11-03 04:00:37 0浏览 收藏

MySQL 要在分组明细后同时生成小计和总计,可以在 GROUP BY 末尾加上 WITH ROLLUP。单列分组会多出总计行;多列分组则会按照列的先后顺序逐级生成小计,最后再生成总计。汇总行中的分组列通常显示为 NULL,如果源数据本身也允许 NULL,应配合 GROUPING() 判断它是不是 ROLLUP 产生的汇总值。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/group-by-modifiers.html

要点速览
  • GROUP BY year WITH ROLLUP 在各年份之后追加全部年份的总计。
  • GROUP BY year, country, product WITH ROLLUP 会依次得到产品小计、国家小计和总计。
  • GROUPING(column) 返回 1 表示该列的 NULL 是汇总标记,返回 0 表示普通分组值。
  • WHERE 先筛明细,HAVING GROUPING(...) 适合筛选已经生成的汇总行。

先用单列 WITH ROLLUP 生成总计

假设销售数据按年份统计利润。普通 GROUP BY 只会返回每个年份的聚合结果;在末尾加上 WITH ROLLUP 后,MySQL 会再追加一行跨越全部年份的超聚合结果。

-- 建立一个只用于演示分组层级的临时表
CREATE TEMPORARY TABLE sales_summary (
    sale_year INT NOT NULL,
    country VARCHAR(32) NOT NULL,
    product VARCHAR(32) NOT NULL,
    profit DECIMAL(12, 2) NOT NULL
);

-- 按年份统计,并在末尾追加所有年份的总计
SELECT sale_year,
       SUM(profit) AS total_profit
FROM sales_summary
GROUP BY sale_year WITH ROLLUP;

查询返回的最后一行中,sale_year 会显示为 NULL,total_profit 则是所有年份利润之和。这里的 NULL 不是某条销售记录缺少年份,而是 MySQL 用来表示“所有年份”的汇总标记。

MySQL 8.4 文档还给出了等价的 GROUP BY ROLLUP (sale_year) 写法。文章后面的多列示例使用更常见的 GROUP BY ... WITH ROLLUP,这样更容易看出汇总层级。

MySQL WITH ROLLUP 从分组明细到产品小计、国家小计和总计的静态结构说明图
图1:WITH ROLLUP 按分组列顺序追加多级汇总的结构说明图,不是数据库控制台截图。

按分组列顺序生成多级小计

多列 GROUP BY 时,列的顺序就是汇总层级。下面按“年份、国家、产品”分组:最细粒度是年份+国家+产品,产品列被汇总后形成国家内的小计;继续汇总国家和产品形成年度小计;最后三列都进入汇总行,得到总计。

-- 三列从左到右定义汇总层级:年份 -> 国家 -> 产品
SELECT sale_year,
       country,
       product,
       SUM(profit) AS total_profit
FROM sales_summary
GROUP BY sale_year, country, product WITH ROLLUP;

可以把结果理解成四个层级:

结果层级分组列表现含义
明细聚合年份、国家、产品都有值某年某国某产品的利润
产品小计产品为 NULL某年某国的全部产品利润
国家小计国家、产品为 NULL某年的全部国家和产品利润
总计年份、国家、产品都为 NULL全部数据的利润

因此,想把“国家小计”放在别的业务维度上,不能只调整展示文案,而要重新排列 GROUP BY 列。ROLLUP 是沿着分组列顺序产生前缀层级,不是任意组合所有维度。

用 GROUPING() 区分汇总 NULL

如果业务字段允许真实的 NULL,仅看结果中的 NULL 就不够了。例如,某个商品没有录入产品名时,普通分组也可能出现 product IS NULL 的明细聚合行。MySQL 提供 GROUPING(product) 来区分这两种情况:普通分组返回 0,ROLLUP 产生的超聚合列返回 1。

-- 同时输出每个维度是否处于 ROLLUP 汇总层级
SELECT sale_year,
       country,
       product,
       SUM(profit) AS total_profit,
       GROUPING(sale_year) AS is_year_total,
       GROUPING(country) AS is_country_total,
       GROUPING(product) AS is_product_total
FROM sales_summary
GROUP BY sale_year, country, product WITH ROLLUP;

例如,某行的 product 是 NULL 且 is_product_total=0,说明它可能是源数据中的真实空值;如果 is_product_total=1,则说明这一行是产品维度被汇总后的产品小计。这个判断也适用于国家和年份列。

MySQL GROUPING 区分真实 NULL 与 WITH ROLLUP 汇总 NULL 的静态关系说明图
图2:真实 NULL 与 ROLLUP 汇总 NULL 通过 GROUPING() 区分的结构说明图,不是实际查询结果截图。

给汇总行加标签并筛选

直接显示 NULL 对报表用户不够友好,可以在查询列中根据 GROUPING() 替换成“小计”或“总计”。保留普通数据的真实 NULL,只替换函数返回 1 的汇总值。

-- 只给 ROLLUP 产生的空维度加标签,保留业务数据里的真实 NULL
SELECT IF(GROUPING(sale_year) = 1, '全部年份', CAST(sale_year AS CHAR)) AS year_label,
       IF(GROUPING(country) = 1, '全部国家', COALESCE(country, '未填写国家')) AS country_label,
       IF(GROUPING(product) = 1, '全部产品', COALESCE(product, '未填写产品')) AS product_label,
       SUM(profit) AS total_profit
FROM sales_summary
GROUP BY sale_year, country, product WITH ROLLUP;

如果只想查看小计和总计,可以用多参数形式的 GROUPING() 在 HAVING 中筛选。只要任意一个分组维度进入了汇总层级,组合结果就不为 0。

-- 过滤掉最细粒度明细,只保留产品小计、国家小计和总计
SELECT sale_year,
       country,
       product,
       SUM(profit) AS total_profit
FROM sales_summary
GROUP BY sale_year, country, product WITH ROLLUP
HAVING GROUPING(sale_year, country, product)  0;

这里的多参数结果是一个位掩码,右侧参数对应低位。实际写报表时,如果只需要某一级,分别检查目标列的 GROUPING() 值通常更直观,例如只保留产品小计可以使用 GROUPING(product)=1 AND GROUPING(country)=0。

处理排序、WHERE、HAVING 与 LIMIT 边界

ROLLUP 的汇总行是在分组聚合之后形成的,几个常见条件要放在正确位置。

-- WHERE 先缩小原始数据范围,再对过滤后的数据生成小计和总计
SELECT sale_year,
       country,
       product,
       SUM(profit) AS total_profit
FROM sales_summary
WHERE sale_year >= 2025
GROUP BY sale_year, country, product WITH ROLLUP
-- HAVING 可以识别已经生成的 ROLLUP 行
HAVING GROUPING(sale_year, country, product)  0
-- 将总计放到结果前面;明细排序规则可按报表需要继续补充
ORDER BY GROUPING(sale_year) DESC, sale_year;
  • WHERE 过滤源表行,适合限定年份、租户或业务范围;它不能用来判断 ROLLUP 后才出现的汇总 NULL。
  • HAVING 位于聚合之后,可以使用 GROUPING() 选择小计或总计。
  • ORDER BY GROUPING(sale_year) DESC 可以把总计行排在前面;不写排序时,不要把默认返回顺序当成业务契约。
  • LIMIT 作用于已经包含 ROLLUP 行的结果,截断时可能把一个汇总层级切开,报表分页要特别谨慎。

如果只是需要一个总数,而不需要明细、小计和总计同时返回,单独执行聚合查询通常更容易维护。ROLLUP 更适合一次性生成层级报表,或把多级汇总交给同一个 SQL 结果集。

相关问题

WITH ROLLUP 和 GROUP BY ROLLUP() 有什么区别?

在 MySQL 8.4 的文档示例中,两者都是 ROLLUP 修饰语的写法。日常维护时选团队更熟悉的一种,并保持分组列顺序一致。

为什么 ROLLUP 的汇总行显示为 NULL?

MySQL 用分组列上的 NULL 表示该维度已经被汇总。若源数据也可能为 NULL,应使用 GROUPING() 判断它是不是超聚合标记。

可以用 WHERE product IS NULL 只取小计吗?

不建议这样做。ROLLUP 的汇总 NULL 在较晚阶段写入结果,且真实数据也可能为 NULL;使用 HAVING GROUPING(product)=1 才能明确筛选产品小计。

多列 ROLLUP 为什么会多出很多行?

每个分组列前缀都会形成一个汇总层级。分组列越多,层级越多;应先确认报表需要的维度顺序,再决定是否使用 ROLLUP。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL REGEXP_LIKE 怎样判断字符串是否匹配正则MySQL REGEXP_LIKE 怎样判断字符串是否匹配正则
上一篇
MySQL REGEXP_LIKE 怎样判断字符串是否匹配正则
MySQL ST_GeomFromText 怎样把 WKT 文本转成空间对象
下一篇
MySQL ST_GeomFromText 怎样把 WKT 文本转成空间对象
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    851次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    855次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    936次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    910次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    739次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码