转自:[https://www.yiibai.com/sql/sql-rollup.html](https://www.yiibai.com/sql/sql-rollup.html) # 1. SQL ROLLUP简介 `ROLLUP`是`GROUP BY`子句的扩展。 `ROLLUP`选项允许包含表示小计的额外行,通常称为超级聚合行,以及总计行。 通过使用`ROLLUP`选项,可以使用单个查询生成多个分组集。 > 注意,分组集是一组用于分组的列。 例如,一个由仓库返回库存的查询,分组集是(`warehouse`)。 ```sql SELECT warehouse, SUM(quantity) qty FROM inventory GROUP BY warehouse; ``` 有关`GROUPING SETS`的更多信息,请查看分组集教程。 以下是SQL `ROLLUP`的基本语法: ```sql SELECT c1, c2, aggregate_function(c3) FROM table GROUP BY ROLLUP (c1, c2); ``` `ROLLUP`假定输入列之间存在层次结构。 例如,如果输入列是`(c1,c2)`,则层次结构`c1 > c2`。 `ROLLUP`生成考虑此层次结构有意义的所有分组集。 这就是为什么我们经常使用`ROLLUP`来生成小计和总计以用于报告目的。 在上面的语法中,`ROLLUP(c1,c2)`生成以下三个分组集: * (c1,c2) * (c1) * () Oracle,Microsoft SQL Server和PostgreSQL支持此语法。 但是,MySQL的语法略有不同,如下所示: ```sql SELECT c1, c2, aggregate_function(c3) FROM table_name GROUP BY c1, c2 WITH ROLLUP; ``` # 2. SQL ROLLUP示例 我们将使用在[GROUPING SETS教程](GROUPING SETS用法)中设置的`inventory`表进行演示。 ```sql mysql> select * from inventory; +---------------+---------+----------+----------+ | warehouse | product | model | quantity | +---------------+---------+----------+----------+ | San Jose | iPhone | 6s | 100 | | San Fransisco | iPhone | 6s | 50 | | San Jose | iPhone | 7 | 50 | | San Fransisco | iPhone | 7 | 10 | | San Jose | iPhone | X | 150 | | San Fransisco | iPhone | X | 200 | | San Jose | Samsung | Galaxy S | 200 | | San Fransisco | Samsung | Galaxy S | 200 | | San Fransisco | Samsung | Note 8 | 100 | | San Jose | Samsung | Note 8 | 150 | +---------------+---------+----------+----------+ 10 rows in set ``` ## 2.1. SQL ROLLUP有一个列示例 以下语句使用`GROUP BY`子句和`SUM()`函数按仓库查找总库存: ```sql SELECT warehouse, SUM(quantity) FROM inventory GROUP BY warehouse; +---------------+---------------+ | warehouse | SUM(quantity) | +---------------+---------------+ | San Fransisco | 560 | | San Jose | 650 | +---------------+---------------+ 2 rows in set ``` 要检索所有仓库中的总产品数,请将`ROLLUP`添加到`GROUP BY`子句,如下所示: ```sql SELECT warehouse, SUM(quantity) FROM inventory GROUP BY ROLLUP(warehouse); ``` 执行上面示例代码,得到以下结果: ``` warehouse | sum ---------------+------ null | 1210 San Fransisco | 560 San Jose | 650 ``` 正如在结果中看到的那样,`warehouse`列中的`NULL`值指定了总计超级聚合行。 在此示例中,`ROLLUP`选项使查询生成另一行,显示所有仓库中的总产品数量。 要使输出更具可读性,可以使用`COALESCE()`函数将`NULL`值替换`All`值,如下所示: ```sql SELECT COALESCE(warehouse, 'All warehouses') AS warehouse, SUM(quantity) FROM inventory GROUP BY ROLLUP (warehouse); ``` 执行上面示例代码,得到以下结果: ``` warehouse | sum ----------------+------ All warehouses | 1210 San Fransisco | 560 San Jose | 650 ``` ## 2.2. SQL ROLLUP有多列示例 以下语句按`warehouse`和`product`计算库存: ```sql SELECT warehouse, product, SUM(quantity) FROM inventory GROUP BY warehouse, product; ``` 执行上面示例代码,得到以下结果: ``` warehouse | product | sum ---------------+---------+----- San Fransisco | iPhone | 260 San Fransisco | Samsung | 300 San Jose | iPhone | 300 San Jose | Samsung | 350 ``` 将`ROLLUP`添加到`GROUP BY`子句: ```sql SELECT warehouse, product, SUM(quantity) FROM inventory GROUP BY ROLLUP (warehouse , product); ``` 执行上面示例代码,得到以下结果: ``` warehouse | product | sum ---------------+---------+------ null | null | 1210 -- 总计 San Fransisco | iPhone | 260 San Fransisco | Samsung | 300 San Jose | iPhone | 300 San Jose | Samsung | 350 San Fransisco | null | 560 -- San Fransisco仓库的小计 San Jose | null | 650 -- San Jose仓库的小计 ``` 请注意,输出包含两个分析级别的摘要信息,而不仅仅是一个: * 在指定仓库的每组产品行之后,将显示一个额外的摘要行,显示总库存。 在这些行中,`product`列中的值设置为`NULL`。 * 在所有行之后,将显示一个额外的摘要行,显示所有仓库和产品的总库存。 在这些行中,`warehouse` 和 `product` 列中的值设置为`NULL`。 ## 2.3. SQL ROLLUP带有部分汇总的示例 可以使用`ROLLUP`执行部分汇总,以减少计算的小计数,如以下示例所示: ```sql SELECT warehouse, product, SUM(quantity) FROM inventory GROUP BY warehouse, ROLLUP (product); ``` 执行上面示例代码,得到以下结果: ``` warehouse | product | sum ---------------+---------+----- San Fransisco | iPhone | 260 San Fransisco | Samsung | 300 San Jose | iPhone | 300 San Jose | Samsung | 350 San Fransisco | null | 560 San Jose | null | 650 ``` 在此示例中,`ROLLUP`仅为`product`列而不是`warehouse`列生成超级聚合摘要。