MySql的分组函数 ROLLUP 语法及完美解决方案

 更新时间:2026年03月03日 10:30:09   作者:xixi_666  
这篇文章总结了在MySQL中如何使用`GROUP BY`和`ROLLUP`来实现分组汇总,通过`WITH ROLLUP`和`GROUPING()`函数,可以灵活地控制汇总级别,并使用`HAVING`子句来过滤掉中间汇总行,只保留明细和最终总计行,感兴趣的朋友跟随小编一起看看吧
  • Oracle: GROUP BY ROLLUP(字段A)
  • MySQL: GROUP BY 字段A WITH ROLLUP

解决方案1:使用 WITH ROLLUPGROUPING()

SELECT 
    CASE 
        WHEN GROUPING(C_JXDM) = 1 THEN 2
        ELSE 0 
    END AS N_GROUPING,
    -- GROUPING(C_JXDM) C_JXDM_GROUPING,
    -- GROUPING(C_PXLB) C_PXLB_GROUPING,
    COALESCE(C_JXDM, '合计') AS C_JXDM,
    COALESCE(C_PXLB, '') AS C_PXLB,
    COUNT(*) AS N_CNT
FROM (
    -- 模拟你的数据表
    SELECT 'name1' AS name, '103001' AS C_JXDM, '1' AS C_PXLB
    UNION ALL
    SELECT 'name2', '103001', '1'
    UNION ALL
    SELECT 'name3', '103001', '2'
    UNION ALL
    SELECT 'name4', '103001', '3'
    UNION ALL
    SELECT 'name5', '103001', '3'
    UNION ALL
    SELECT 'name6', '112001', '1'
    UNION ALL
    SELECT 'name7', '112001', '1'
    UNION ALL
    SELECT 'name8', '138001', '2'
) AS t
GROUP BY C_JXDM, C_PXLB WITH ROLLUP
HAVING GROUPING(C_PXLB) = 0 OR (GROUPING(C_JXDM) = 1 AND GROUPING(C_PXLB) = 1)
ORDER BY 
    GROUPING(C_JXDM) ASC,
    C_JXDM,
    GROUPING(C_PXLB) ASC,
    C_PXLB;
N_GROUPING	C_JXDM	C_PXLB	N_CNT
0	103001	1	2
0	103001	2	1
0	103001	3	2
0	112001	1	2
0	138001	2	1
2	合计		8

解决方案2:更简洁的写法(MySQL 8.0+)

WITH sample_data AS (
    SELECT 'name1' AS name, '103001' AS C_JXDM, '1' AS C_PXLB
    UNION ALL SELECT 'name2', '103001', '1'
    UNION ALL SELECT 'name3', '103001', '2'
    UNION ALL SELECT 'name4', '103001', '3'
    UNION ALL SELECT 'name5', '103001', '3'
    UNION ALL SELECT 'name6', '112001', '1'
    UNION ALL SELECT 'name7', '112001', '1'
    UNION ALL SELECT 'name8', '138001', '2'
)
SELECT 
    CASE 
        WHEN GROUPING(C_JXDM) = 1 THEN 2
        WHEN GROUPING(C_PXLB) = 0 THEN 0
        ELSE 1
    END AS N_GROUPING,
    -- GROUPING(C_JXDM) C_JXDM_GROUPING,
    -- GROUPING(C_PXLB) C_PXLB_GROUPING,
    COALESCE(C_JXDM, '合计') AS C_JXDM,
    COALESCE(C_PXLB, '') AS C_PXLB,
    COUNT(*) AS N_CNT
FROM sample_data
GROUP BY C_JXDM, C_PXLB WITH ROLLUP
-- HAVING GROUPING(C_PXLB) = 0 OR (GROUPING(C_JXDM) = 1 AND GROUPING(C_PXLB) = 1)
ORDER BY 
    GROUPING(C_JXDM),
    C_JXDM,
    GROUPING(C_PXLB),
    C_PXLB;
N_GROUPING	C_JXDM	C_PXLB	N_CNT
0	103001	1	2
0	103001	2	1
0	103001	3	2
1	103001		5
0	112001	1	2
1	112001		2
0	138001	2	1
1	138001		1
2	合计		8

加上“HAVING GROUPING(C_PXLB) = 0 OR (GROUPING(C_JXDM) = 1 AND GROUPING(C_PXLB) = 1)” 就只列出明细和总计行

解决方案3:如果只需要明细和总计(2级汇总)

WITH sample_data AS (
    SELECT 'name1' AS name, '103001' AS C_JXDM, '1' AS C_PXLB
    UNION ALL SELECT 'name2', '103001', '1'
    UNION ALL SELECT 'name3', '103001', '2'
    UNION ALL SELECT 'name4', '103001', '3'
    UNION ALL SELECT 'name5', '103001', '3'
    UNION ALL SELECT 'name6', '112001', '1'
    UNION ALL SELECT 'name7', '112001', '1'
    UNION ALL SELECT 'name8', '138001', '2'
)
SELECT 
    GROUPING(C_JXDM) + GROUPING(C_PXLB) AS N_GROUPING,
    IFNULL(C_JXDM, '合计') AS C_JXDM,
    IFNULL(C_PXLB, '') AS C_PXLB,
    COUNT(*) AS N_CNT
FROM sample_data
GROUP BY C_JXDM, C_PXLB WITH ROLLUP
HAVING (GROUPING(C_JXDM) = 0 AND GROUPING(C_PXLB) = 0)  -- 明细行
    OR (GROUPING(C_JXDM) = 1 AND GROUPING(C_PXLB) = 1)  -- 总计行
ORDER BY GROUPING(C_JXDM), C_JXDM, GROUPING(C_PXLB), C_PXLB;
N_GROUPING	C_JXDM	C_PXLB	N_CNT
0	103001	1	2
0	103001	2	1
0	103001	3	2
0	112001	1	2
0	138001	2	1
2	合计		8

解释:

  • N_GROUPING 值
    • 0:表示明细行(既有C_JXDM分组,也有C_PXLB分组)
    • 2:表示总计行(两个维度都汇总了)
  • GROUPING() 函数
    • 返回0表示该列参与分组
    • 返回1表示该列是ROLLUP汇总的结果
  • COALESCE/IFNULL:用于处理ROLLUP产生的NULL值
  • HAVING 子句
    • 过滤掉中间的汇总行(如每个C_JXDM的小计),只保留明细和最终总计

如果你需要不同级别的汇总(如小计+总计),可以调整HAVING子句的条件。

到此这篇关于MySql的分组函数 ROLLUP 语法的文章就介绍到这了,更多相关mysql分组函数rollup语法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL Workbench下载与使用教程详解

    MySQL Workbench下载与使用教程详解

    这篇文章主要为大家详细介绍了MySQL Workbench下载与使用教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • MySQL六种约束的示例详解(全网最全)

    MySQL六种约束的示例详解(全网最全)

    约束是作用于表中字段上的规则,用于限制存储在表中的数据。这篇文章主要为大家整理了一下MySQL中六种约束的用法,感兴趣的可以了解一下
    2022-07-07
  • MySQL中distinct和group by去重的区别解析

    MySQL中distinct和group by去重的区别解析

    在MySQL中,我们经常需要对查询结果进行去重,而DISTINCT和GROUP BY是实现这一功能的两种常见方法,这篇文章主要介绍了MySQL中distinct和group by去重的区别,需要的朋友可以参考下
    2025-01-01
  • MySql服务器系统变量和状态变量介绍

    MySql服务器系统变量和状态变量介绍

    这篇文章主要介绍了MySql服务器系统变量和状态变量介绍,本文分别讲解了它们的作用、设置方法和获取方法,需要的朋友可以参考下
    2014-12-12
  • Mysql的索引优化原则详解

    Mysql的索引优化原则详解

    本文详细介绍了MySQL索引优化原则,包括最佳左前缀法则、不要在索引列上做任何计算、避免使用范围条件、避免使用特定运算符等,通过这些原则,可以提高查询效率,避免全表扫描,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • 超详细MySQL使用规范分享

    超详细MySQL使用规范分享

    这篇文章主要介绍了MySQL使用规范,帮助大家更规范的操作MySQL,感兴趣的朋友可以了解下
    2020-08-08
  • mysql 数据库链接状态确认实验(推荐)

    mysql 数据库链接状态确认实验(推荐)

    这篇文章主要介绍了mysql 数据库链接状态确认实验,通过本文我选择 了三种方案给大家详细讲解,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 一文了解Mysql分区的使用

    一文了解Mysql分区的使用

    分区允许根据可以设置为任意大小的规则,跨文件系统分配单个表的多个部分,本文主要介绍了Mysql分区的使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • MySQL高效处理ORDER BY与GROUP BY查询的优化策略

    MySQL高效处理ORDER BY与GROUP BY查询的优化策略

    在高并发、大数据量的业务场景中,SQL 查询性能直接影响系统整体响应速度,本文将深入探讨 MySQL 中排序与分组的执行机制,并提供一系列实用的优化策略,希望对大家有所帮助
    2026-02-02
  • 在MySQL中生成随机密码的方法

    在MySQL中生成随机密码的方法

    这篇文章主要介绍了在MySQL中生成随机密码的方法,作者还给出了密码所对应类型限制的参数表,需要的朋友可以参考下
    2015-05-05

最新评论