当前位置: 代码网 > it编程>数据库>Mysql > MySql的分组函数 ROLLUP 语法及完美解决方案

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

2026年03月03日 Mysql 我要评论
oracle: group by rollup(字段a)mysql: group by 字段a with rollup解决方案1:使用 with rollup和 grouping()select
  • 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语法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com