目录
Grouping Sets
CUBE and ROLLUP
GROUPING和GROUPING_ID函数
Grouping Sets、CUBE 、ROLLUP 、LATERAL VIEW EXPLODE 区别
Grouping Sets
对于经常需要对数据进行多维度的聚合分析的场景,您既需要对a列做聚合,也要对b列做聚合,同时要按照a,b两列同时做聚合,因此需要写很多UNION ALL。但使用Grouping Sets可以非常快速方便地解决此类问题。
MaxCompute中的Grouping Sets功能是对SELECT语句中,Group By子句的扩展,允许您采用多种方式对结果分组,而不必使用多个SELECT语句来实现这一目的。这样能够使MaxCompute的引擎给出更有效的执行计划,从而提高执行性能。
实现示例
准备数据
create table requests LIFECYCLE 20 as
select * from values
(1, 'windows', 'PC', 'Beijing'),
(2, 'windows', 'PC', 'Shijiazhuang'),
(3, 'linux', 'Phone', 'Beijing'),
(4, 'windows', 'PC', 'Beijing'),
(5, 'ios', 'Phone', 'Shijiazhuang'),
(6, 'linux', 'PC', 'Beijing'),
(7, 'windows', 'Phone', 'Shijiazhuang')
as t(id, os, device, city);
您可以通过以下两种方式进行分组。
-
使用多个SELECT语句进行分组。
SELECT NULL, NULL, NULL, COUNT(*)
FROM requests
UNION ALL
SELECT os, device, NULL, COUNT(*)
FROM requests GROUP BY os, device
UNION ALL
SELECT null, null, city, COUNT(*)
FROM requests GROUP BY city;
-
使用Grouping Sets进行分组。
SELECT os,device, city ,COUNT(*)
FROM requests
GROUP BY os, device, city GROUPING SETS((os, device), (city), ());
以上两种方式均产生相同的结果,如下所示:
CUBE and ROLLUP
CUBE和ROLLUP可以认为是特殊的Grouping Sets。
CUBE会枚举指定列的所有可能组合作为Grouping Sets,而ROLLUP会以按层级聚合的方式产生Grouping Sets。
示例如下:
GROUP BY CUBE(a, b, c) 等价于 GROUPING SETS((a,b,c),(a,b),(a,c),(b,c),(a),(b),(c),())
GROUP BY ROLLUP(a, b, c) 等价于 GROUPING SETS((a,b,c),(a,b),(a), ())
GROUP BY CUBE ( (a, b), (c, d) ) 等价于 GROUPING SETS (
( a, b, c, d ),
( a, b ),
( c, d ),
( )
)
GROUP BY ROLLUP ( a, (b, c), d ) 等价于GROUPING SETS (
( a, b, c, d ),
( a, b, c ),
( a ),
( )
)
GROUP BY a, CUBE (b, c), GROUPING SETS ((d), (e)) 等价于 GROUP BY GROUPING SETS (
(a, b, c, d), (a, b, c, e),
(a, b, d), (a, b, e),
(a, c, d), (a, c, e),
(a, d), (a, e)
)
GROUP BY grouping sets((b), (c),rollup(a,b,c)) 等价于 GROUP BY GROUPING SETS (
(b), (c),
(a,b,c), (a,b), (a), ()
)
GROUPING和GROUPING_ID函数
前文中提到,会在Grouping Sets结果中使用NULL充当占位符,所以,您会无法区分占位符NULL与数据中真正的NULL。因此,我们提供了GROUPING函数。
GROUPING函数接受一个列名作为参数,如果结果对应行使用了参数列做聚合,返回0,此时意味着NULL来自输入数据。否则返回1,此时意味着NULL是Grouping Sets的占位符。
此外,我们还提供了GROUPING_ID函数,此函数接受一个或多个列名作为参数。结果是将参数列的GROUPING结果按照BitMap的方式组成整数。
示例如下:
SELECT a,b,c ,COUNT(*),
GROUPING(a) ga, GROUPING(b) gb, GROUPING(c) gc, GROUPING_ID(a,b,c) groupingid
FROM VALUES (1,2,3) as t(a,b,c)
GROUP BY CUBE(a,b,c);
Grouping Sets、CUBE 、ROLLUP 、LATERAL VIEW EXPLODE 区别
- Grouping Sets
- 优点:
- 聚和功能最强大,可以更灵活的组合,对于一些不需要的维度组合可以进行裁剪从而优化性能和存储。
- 缺点
- 当维度较多时候,比如性别、国家、省份、城市、等级、会员、年龄、标签等等,进行组合时候需要枚举的组合太多写起来会比较麻烦。
- 优点:
- CUBE 和 ROLLUP 可以理解为一种特殊的Grouping Sets
- CUBE魔方类似笛卡尔积,会穷举所有组合,此类型的维度聚合场景使用CUBE更简洁。
- ROLLUP是类似下钻的维度组合方式,比如国家、省份、城市这种维度层级归属关系,使用ROLLUP书写会更简洁。
- LATERAL VIEW EXPLODE配合ARRAY写法。
- 当使用习惯时候,这种写法也很顺手,缺点是没有Grouping Sets那么强大灵活的组合灵活裁剪能力。
- 优点是当维度较多、Grouping Sets组合数过多不好书写,比如10个维度中有五个维度需要ALL全聚和,Grouping Sets书写费力,CUBE、ROLLUP又不能支持,此时LATERAL VIEW EXPLODE反而会书写更简洁。
总结:
日常大多情况还是推荐使用Grouping Sets配合Grouping函数,少数场景不便书写时可考虑其他聚和函数。