GROUP BY ROLLUP(字段A)MySQL: GROUP BY 字段A WITH ROLLUP
解决方案1:使用 WITH ROLLUP和 GROUPING()
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 语法的文章就介绍到这了,
