MariaDB使用ROLLUP查询时如何同时保留明细行与各类汇总小计?
问题原因
你之前的ROLLUP查询丢失明细,是因为分组维度仅到「捐赠日期+用户ID」层级,同一分组下的多条明细会被直接聚合计算,自然无法保留单条捐赠记录的行级数据。
解决方案
要同时保留明细、用户维度小计、日期维度合计,需要将分组粒度下沉到单条捐赠记录的唯一标识(DonationID),配合WITH ROLLUP和GROUPING()函数判断聚合层级,生成对应格式的输出:
SELECT CASE -- 判断是日期合计行 WHEN GROUPING(UserContactID) = 1 THEN CONCAT('tot for ', DonationDate) -- 判断是用户维度小计行 WHEN GROUPING(DonationID) = 1 THEN CONCAT('sub for ', UserContactID, ' on ', DonationDate) -- 明细行返回原始日期 ELSE DonationDate END AS DonationDate, -- 小计/合计行用户ID留空 IF(GROUPING(DonationID) = 1 OR GROUPING(UserContactID) = 1, NULL, UserContactID) AS UserContactID, SUM(DonationAmount) AS DonationAmount FROM donations -- 分组顺序从粗到细:日期→用户ID→单条捐赠唯一ID GROUP BY DonationDate, UserContactID, DonationID WITH ROLLUP -- 过滤掉全局总计行(如果需要全局总计可删除此行) HAVING GROUPING(DonationDate) = 0 -- 保证输出顺序和预期一致 ORDER BY DonationDate, UserContactID, DonationID;
逻辑说明
- 分组顺序按「从粗到细」排列,ROLLUP会从最右侧的分组字段开始逐层向上聚合:
- 三个分组字段都不为空时,返回原始单条捐赠明细
- DonationID字段聚合为NULL时,代表当前行是「同日期同用户」的捐赠小计
- UserContactID字段聚合为NULL时,代表当前行是「同日期」的所有捐赠合计
GROUPING()函数返回1代表对应字段是聚合生成的NULL,0代表是原始数据的取值,以此区分不同聚合层级的行输出对应内容。
内容的提问来源于stack exchange,提问作者riddley walker
相关产品推荐
相关产品推荐

