如何在LEFT JOIN的小计/总计行中置空非汇总列
解决MySQL ROLLUP汇总行名称显示问题
场景说明
现有两张表:
交易表 transaction
| code_id | amount |
|---|---|
| 1 | 10.00 |
| 1 | 10.00 |
| 2 | 50.00 |
| 2 | 50.00 |
代码描述表 description
| code_id | name |
|---|---|
| 1 | Monthly fee |
| 2 | Yearly fee |
执行原查询按code_id分组求和并生成总计:
SELECT transaction.code_id, SUM(transaction.amount), description.name FROM transaction LEFT JOIN description on description.code_id = transaction.code_id GROUP BY code_id WITH ROLLUP;
得到的结果中,总计行的name字段随机取了描述表中的值(如示例中的Yearly Fee),需要将总计行的name改为grand total(或置空),多字段分组时的小计行也需做类似处理,使用MySQL 5.6版本。
解决方案
利用MySQL的GROUPING()函数判断当前行是否为ROLLUP生成的汇总行,通过条件语句替换name字段的值:
单字段分组场景
修改后的查询语句:
SELECT transaction.code_id, SUM(transaction.amount) AS amount, IF(GROUPING(code_id), 'grand total', description.name) AS name FROM transaction LEFT JOIN description ON description.code_id = transaction.code_id GROUP BY code_id WITH ROLLUP;
逻辑说明:
GROUPING(code_id)会在当前行是ROLLUP生成的总计行(即code_id为NULL)时返回1,否则返回0- 通过
IF()函数,当判断为总计行时,将name设为grand total,否则保留原描述名称;若要置空,将'grand total'替换为NULL即可
多字段分组场景
假设需按code_id和type(示例新增字段)分组并生成小计、总计,可使用CASE语句区分不同层级的汇总行:
SELECT transaction.code_id, transaction.type, SUM(transaction.amount) AS amount, CASE WHEN GROUPING(code_id) = 1 THEN 'grand total' WHEN GROUPING(type) = 1 THEN CONCAT('Subtotal: ', description.name) ELSE description.name END AS name FROM transaction LEFT JOIN description ON description.code_id = transaction.code_id GROUP BY code_id, type WITH ROLLUP;
逻辑说明:
GROUPING(code_id) = 1对应最顶层的总计行,显示grand totalGROUPING(type) = 1对应code_id分组下的小计行,显示自定义的小计名称- 普通分组行保留原描述名称
内容的提问来源于stack exchange,提问作者trilogy
相关产品推荐
相关产品推荐

