如何在不使用子查询或冗余连接的情况下查询分组、分组总计及总计?
解决方案:用ROLLUP/GROUPING SETS实现分组、分组总计与全局总计
嘿,看来你已经在琢磨分组统计的最佳姿势了!其实不用子查询或者多余连接的话,用SQL标准里的ROLLUP或者GROUPING SETS就能完美解决你的需求——这俩就是专门用来生成分组、分组总计和全局总计的工具,完全符合你的要求。
先来说说ROLLUP:分层统计的首选
如果你需要的是分层递进的统计结果(比如先按「区域+产品」分组统计,再出每个区域的总计,最后出全局总计),ROLLUP是最顺手的。它会根据你指定的分组字段层级,自动生成各级总计行,全程不用额外子查询或连接。
举个实际例子,假设我们有个sales销售表,结构是这样的:
CREATE TABLE sales ( region VARCHAR(50), -- 销售区域 product VARCHAR(50), -- 产品名称 amount DECIMAL(10,2) -- 销售额 );
要同时拿到「区域+产品的分组统计」、「区域总计」和「全局总计」,直接这么写就行:
SELECT region, product, SUM(amount) AS total_sales FROM sales GROUP BY ROLLUP(region, product);
返回的结果会分成三类行:
- 当
region和product都有具体值时,这是单个产品的分组销售额 - 当
product为NULL、region有值时,这是对应区域的总计 - 当
region和product都为NULL时,这是所有数据的全局总计
如果想让总计行的显示更友好(比如把NULL换成「全部区域」「全部产品」),可以用GROUPING()函数判断是否是总计行:
SELECT CASE WHEN GROUPING(region) = 1 THEN '全部区域' ELSE region END AS region, CASE WHEN GROUPING(product) = 1 THEN '全部产品' ELSE product END AS product, SUM(amount) AS total_sales FROM sales GROUP BY ROLLUP(region, product);
灵活自定义统计组合?用GROUPING SETS
如果你不需要严格的分层,而是想灵活指定要统计的分组组合(比如只需要「区域+产品的分组统计」和「全局总计」,跳过区域总计),那GROUPING SETS更适合。它允许你直接列出所有想要的统计维度组合:
SELECT region, product, SUM(amount) AS total_sales FROM sales GROUP BY GROUPING SETS( (region, product), -- 按区域+产品分组统计 () -- 全局总计 );
要是需要区域总计+全局总计,也可以直接加进去:
GROUP BY GROUPING SETS( (region, product), (region), () );
为啥这俩方法符合你的要求?
- 完全不需要子查询:所有统计逻辑都在一个SELECT语句里完成,不用嵌套查询
- 不需要额外连接:直接基于原表的GROUP BY扩展功能实现,没有多余的表关联操作
你之前尝试用PARTITION BY的思路其实是窗口函数的方向,但窗口函数是给每行原数据附加统计值,而这里我们需要的是聚合后的分组行+总计行,所以ROLLUP/GROUPING SETS才是更直接的解决方案,也不会和GROUP BY产生冲突。
内容的提问来源于stack exchange,提问作者user45867
相关产品推荐
相关产品推荐

