增强的聚合,多维数据集,分组和汇总

本文档介绍了 SELECT 语句的 GROUP BY 子句的增强的聚合功能。

Version

Hive 0.10.0 中添加了分组集,CUBE 和 ROLLUP 运算符以及 GROUPING__ID 函数。
参见HIVE-2397HIVE-3433HIVE-3471HIVE-3613
另请参阅HIVE-3552,了解 Hive 0.11.0 中添加的改进。

Version

从 Hive 2.3.0 开始,GROUPING__ID 符合其他 SQL 引擎中的语义(请参见HIVE-16102)。
Hive 2.3.0 中也添加了对 SQL 分组功能的支持(请参阅HIVE-15409)。

有关 GROUP BY 的一般信息,请参见《语言手册》中的GroupBy

GROUPING SETS 子句

GROUP BY 中的 GROUPING SETS 子句允许我们在同一记录集中指定多个 GROUP BY 选项。所有 GROUPING SET 子句可以用 UNION 连接的几个 GROUP BY 查询来逻辑表示。表 1 显示了几个这样的等效语句。这有助于形成 GROUPING SETS 子句的思想。 GROUPING SETS 子句中的空白集()计算总体合计。

表 1-GROUPING SET 查询和等效的 GROUP BY 查询

使用 GROUPING SETS 汇总查询GROUP BY 的等效聚合查询
从 tab1 中选择 a,b,SUM(c)GROUP BY a,b 分组集((a,b))从 tab1 GROUP BY a,b 中选择 a,b,SUM(c)
从 tab1 中选择 a,b,SUM(c)(a,b)分组集((a,b),a)从 tab1 GROUP BY a,b 中选择 a,b,SUM(c)


Note





UNION



从 tab1 GROUP BY a |中选择 a,null,SUM(c)。
|从 tab1 GROUP BY a,b 中选择 a,b,SUM(c)分组集(a,b)|从 tab1 GROUP BY a 中选择 a,null,SUM(c)

[!NOTE]




UNION



从 tab1 GROUP BY b |中选择 NULL,b,SUM(c)
|从 tab1 GROUP BY a,b GROUPING SETS((a,b),a,b,())中选择 a,b,SUM(c)|从 tab1 GROUP BY a,b 中选择 a,b,SUM(c)

[!NOTE]




UNION



从 tab1 GROUP BY 中选择 a,null,SUM(c)

[!NOTE]




UNION



SELECT null,b,SUM(c)from tab1 GROUP BY null,b

[!NOTE]




UNION



从 tab1 中选择 NULL,NULL,SUM(c)

Grouping__ID function

当显示某列的汇总时,其值为 null。如果列本身具有一些空值,则可能会发生冲突。需要某种方式在列中标识 NULL,这意味着聚合,在列中标识 NULL,这意味着值。 GROUPING__ID 函数是解决该问题的方法。

该函数返回一个对应于每一列是否存在的位向量。对于每一列,如果该列已聚合在结果集中的行中,则该行的值将产生“ 1”,否则该值为“ 0”。当数据中存在空值时,可以使用它来区分。

考虑以下示例:

Column1 (key)Column2 (value)
1NULL
11
22
33
3NULL
45

以下查询:

SELECT key, value, GROUPING__ID, count(*)
FROM T1
GROUP BY key, value WITH ROLLUP;

将得到以下结果:

第 1 列(键)第 2 栏(值)GROUPING__IDcount(*)
NULLNULL36
1NULL12
1NULL01
1101
2NULL11
2201
3NULL12
3NULL01
3301
4NULL11
4501

注意,第三列是所选列的位向量。
对于第一行,没有选择任何列。
对于第二行,仅选择第一列,这说明了值 1.
对于第三行,两个列均被选中(第二列恰好为空),这说明了值 0.

Grouping function

分组功能指示对于给定的行,GROUP BY 子句中的表达式是否聚合。值 0 表示作为分组集一部分的列,而值 1 表示不作为分组集一部分的列。

回到上面的示例,考虑以下查询:

SELECT key, value, GROUPING__ID,
  grouping(key, value), grouping(value, key), grouping(key), grouping(value),
  count(*)
FROM T1
GROUP BY key, value WITH ROLLUP;

该查询将产生以下结果。

第 1 列(键)第 2 栏(值)GROUPING__IDgrouping(key, value)grouping(value, key)grouping(key)grouping(value)count(*)
NULLNULL333116
1NULL112012
1NULL000001
11000001
2NULL112011
22000001
3NULL112012
3NULL000001
33000001
4NULL112011
45000001

多维数据集和汇总

通用语法为 WITH CUBE/ROLLUP。它仅与 GROUP BY 一起使用。 CUBE 在其参数中创建列集合的所有可能组合的小计。一旦我们在一组维度上计算出 CUBE,就可以得到这些维度上所有可能的聚合问题的答案。

在这里也许还值得一提
GROUP BY a,b,c WITH CUBE 等效于
按 a,b,c 分组分组((a,b,c),(a,b),(b,c),(a,c),(a),(b),(c),() )。

ROLLUP 子句与 GROUP BY 一起用于在维的层次结构级别上计算聚合。
使用 ROLLUP 的 GROUP BY a,b,c 假定层次结构是“ a”向下钻取到“ b”向下钻取到“ c”。

GROUP BY a,b,c,WITH ROLLUP 等效于 GROUP BY a,b,c GROUPING SETS((a,b,c),(a,b),(a),())。

hive.new.job.grouping.set.cardinality

是否应启动新的 Map 缩减作业以对集合/汇总/多维数据集进行分组。
对于类似查询的查询:从 T 组中按汇总选择 a,b,c 来选择 a,b,c,count(1);
每行创建 4 行:(a,b,c),(a,b,null),(a,null,null),(null,null,null)
如果 T 的基数非常高,则可能导致跨越 Map 缩小边界的爆炸
而且 Map 端的聚合效果不是很好。

此参数决定配置单元是否应添加其他 Map 减少作业。如果分组
基数(在上面的示例中为 4)大于此值,则在
假设原始分组依据将减少数据大小。

分组__ID 功能(在 Hive 2.3.0 之前)

Hive 2.3.0 中修复了 grouping__ID 函数,因此该版本之前的行为有所不同(这是预期的)。对于每一列,如果该列已聚合在该行中,则该函数将返回值“ 0”,否则该值为“ 1”。

因此,以下查询:

SELECT key, value, GROUPING__ID, count(*)
FROM T1
GROUP BY key, value WITH ROLLUP;

将得到以下结果。

第 1 列(键)第 2 栏(值)GROUPING__IDcount(*)
NULLNULL06
1NULL12
1NULL31
1131
2NULL11
2231
3NULL12
3NULL31
3331
4NULL11
4531

注意,第三列是所选列的位向量。
对于第一行,没有选择任何列。
对于第二行,仅选择第一列,这解释了计数 2.
对于第三行,两个列均被选中(第二列恰好为空),这说明计数为 1.