转自: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
的基本语法:
- snippet.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的语法略有不同,如下所示:
- snippet.sql
SELECT c1, c2, aggregate_function(c3) FROM TABLE_NAME GROUP BY c1, c2 WITH ROLLUP;
2. SQL ROLLUP示例
我们将使用在GROUPING SETS教程中设置的inventory
表进行演示。
- snippet.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()
函数按仓库查找总库存:
- snippet.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
子句,如下所示:
- snippet.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
值,如下所示:
- snippet.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
计算库存:
- snippet.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
子句:
- snippet.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
执行部分汇总,以减少计算的小计数,如以下示例所示:
- snippet.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
列生成超级聚合摘要。