在SQL数据处理工作中,多维度层级统计是常见需求,比如电商场景中需要同时统计每个商品类目、每个店铺以及所有店铺的总销售额,传统实现方式需要分别编写不同维度的查询语句再合并结果,不仅代码冗余,执行效率也较低。ROLLUP作为SQL标准中的聚合扩展功能,可以在单个查询中自动生成从细粒度到粗粒度的多层汇总结果,完美解决这类问题。

ROLLUP的基本语法
ROLLUP是GROUP BY子句的扩展,语法格式如下:
SELECT 维度列1, 维度列2, 聚合函数(指标列) AS 指标名 FROM 表名 GROUP BY ROLLUP(维度列1, 维度列2)
ROLLUP后面的维度列顺序决定了汇总的层级,假设维度列顺序是A、B,那么ROLLUP会生成三层汇总结果:
- 第一层:按A和B两个维度分组,统计对应指标
- 第二层:按A维度分组,统计对应指标(B维度置为NULL,代表该层是A维度的汇总)
- 第三层:全表汇总,A和B维度都置为NULL,代表所有数据的汇总
ROLLUP使用示例
假设我们有一张销售数据表sale_data,表结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| region | VARCHAR | 销售大区 |
| province | VARCHAR | 省份 |
| sale_amount | DECIMAL | 销售额 |
现在需要统计每个大区下各省份的销售额,同时统计每个大区的总销售额,以及所有大区的总销售额,使用ROLLUP的实现代码如下:
SELECT
region,
province,
SUM(sale_amount) AS total_sale
FROM sale_data
GROUP BY ROLLUP(region, province)
ORDER BY region, province
执行上述查询后,结果会包含以下几类数据:
- region和province都不为NULL的行:对应某个大区下某个省份的销售汇总
- region不为NULL、province为NULL的行:对应某个大区所有省份的销售汇总
- region和province都为NULL的行:对应所有大区的总销售汇总
ROLLUP使用注意事项
维度顺序的影响
ROLLUP的汇总层级严格按照括号内维度列的顺序生成,如果调整维度顺序为ROLLUP(province, region),那么汇总层级会变成先按省份和region分组,再按省份汇总,最后全表汇总,和之前的层级完全不同,使用时需要根据需求确定维度顺序。
NULL值的区分
ROLLUP生成的汇总行中,高层级维度会显示为NULL,如果原始数据中存在NULL值,需要额外处理区分。可以通过GROUPING()函数判断当前行是否是汇总行,GROUPING(维度列)返回1代表该列是汇总生成的NULL,返回0代表原始数据的NULL。示例代码如下:
SELECT
region,
province,
SUM(sale_amount) AS total_sale,
GROUPING(region) AS is_region_summary,
GROUPING(province) AS is_province_summary
FROM sale_data
GROUP BY ROLLUP(region, province)
ORDER BY region, province
与其他聚合函数结合
ROLLUP可以和COUNT、AVG、MAX、MIN等所有聚合函数结合使用,只需要将对应的聚合函数替换SUM即可,比如统计每个层级的订单数量:
SELECT
region,
province,
COUNT(order_id) AS order_count
FROM sale_data
GROUP BY ROLLUP(region, province)
ORDER BY region, province
ROLLUP与CUBE的区别
除了ROLLUP之外,SQL还有CUBE功能也可以实现多维度汇总,二者的区别在于:ROLLUP只生成从左到右的层级汇总,而CUBE会生成所有维度组合的交叉汇总。比如CUBE(region, province)除了生成ROLLUP的所有结果之外,还会生成按province分组的汇总行,也就是不区分大区的单省份汇总,使用时需要根据统计需求选择对应的功能。