GroupBy
[TOC]
Group By Syntax
groupByClause: GROUP BY groupByExpression (, groupByExpression)*
groupByExpression: expression
groupByQuery: SELECT expression (, expression)* FROM src groupByClause?
groupByExpression的列需要通过名称来指定,不能使用位置编号。但是从hive0.11.0开始,可以设置参数 hive.groupby.orderby.position.alias=true
来使用位置标号(默认为false)
Simple Examples
计算表的行数
SELECT COUNT(*) FROM table2;
在不包含HIVE-287的版本中,需要使用COUNT(1)来代替COUNT(*)
按性别来统计用户的数量
INSERT OVERWRITE TABLE pv_gender_sum
SELECT pv_users.gender, count (DISTINCT pv_users.userid)
FROM pv_users
GROUP BY pv_users.gender;
多种聚合操作可以同时操作,但是,不能有俩种聚合操作包含不同的DISTINCT列。 如下的操作是可以的,因为count(DISTINCT) 和 sum(DISTINCT) 指向了相同的列
INSERT OVERWRITE TABLE pv_gender_agg
SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(*), sum(DISTINCT pv_users.userid)
FROM pv_users
GROUP BY pv_users.gender;
然而,需要的查询是不允许的, 我们不允许在同一查询中包含不同的DISTINCT表达式
INSERT OVERWRITE TABLE pv_gender_agg
SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(DISTINCT pv_users.ip)
FROM pv_users
GROUP BY pv_users.gender;
Select statement and group by clause
使用group by时, select 只能包含group by 中的字段, 当然,select 中可以包含任意的聚合函数
例如:
CREATE TABLE t1(a INTEGER, b INTGER);
group by 查询
SELECT
a,
sum(b)
FROM
t1
GROUP BY
a;
以上sql正常,因为select包含了groupby中的a 和一个聚合函数sum
SELECT
a,
b
FROM
t1
GROUP BY
a;
以上sql不能正常运行,因为b不在groupby中
Advanced Features
Multi-Group-By Inserts
aggregations 和 select 的输出可以进一步被输入到表中或者hdfs文件中(需要使用hdfs组件)
FROM pv_users
INSERT OVERWRITE TABLE pv_gender_sum
SELECT pv_users.gender, count(DISTINCT pv_users.userid)
GROUP BY pv_users.gender
INSERT OVERWRITE DIRECTORY '/user/facebook/tmp/pv_age_sum'
SELECT pv_users.age, count(DISTINCT pv_users.userid)
GROUP BY pv_users.age;
Map-side Aggregation for Group By
hive.map.aggr
来控制如果做聚合, 默认为false。 当设置为true时,hive将在map阶段执行第一阶段的聚合操作。 这样通常会提高效率,但是需要更大的内存。
set hive.map.aggr=true;
SELECT COUNT(*) FROM table2;
Grouping Sets, Cubes, Rollups, and the GROUPING__ID Function
从hive0.10.0开始,添加了Grouping sets, Cube, rollup操作,以及 Group_ID 方法
Grouping sets clause
Grouping 集合分区让我们可以在相同的数据集下,制定多个group by参数。grouping set分区在逻辑上可以表示为多个group by子句的union。 表格1 展现了几种相同的描述方式 在grouping sets中,一个空的set()会被解释为整个聚合操作
grouping sets
group by
SELECT a, b, SUM(c) FROM tab1 GROUP BY a, b GROUPING SETS ( (a,b) )
SELECT a, b, SUM(c) FROM tab1 GROUP BY a, b
SELECT a, b, SUM( c ) FROM tab1 GROUP BY a, b GROUPING SETS ( (a,b), a)
SELECT a, b, SUM( c ) FROM tab1 GROUP BY a, b UNION SELECT a, null, SUM( c ) FROM tab1 GROUP BY a
SELECT a,b, SUM( c ) FROM tab1 GROUP BY a, b GROUPING SETS (a,b)
SELECT a, null, SUM( c ) FROM tab1 GROUP BY a union SELECT null, b, SUM( c ) FROM tab1 GROUP BY b
SELECT a, b, SUM( c ) FROM tab1 GROUP BY a, b GROUPING SETS ( (a, b), a, b, ( ) )
SELECT a, b, SUM( c ) FROM tab1 GROUP BY a, b union SELECT a, null, SUM( c ) FROM tab1 GROUP BY a, null union SELECT null, b, SUM( c ) FROM tab1 GROUP BY null, b union SELECT null, null, SUM( c ) FROM tab1
Cubes and Rollups
WITH CUBE/ROLLUP 只能用于Group by环境下, Cube 用group by的列集创建了一个具有所有可能组合的子集合。一旦计算了维度集合的cube, 我们就能够获取这些维度的所有可能的聚合操作
cube
group by
GROUP BY a, b, c WITH CUBE
GROUP BY a, b, c GROUPING SETS ((a,b,c), (a, b), (b, c), (a, c), (a), (b), (c), ())
rollup
group by
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
grouping sets/rollup/cubes 都是导致一个mr的任务被加载,类如: select a, b, c, count(1) from T group by a, b, c with rollup;
, 每行数据都是生成四行 (a,b,c), (a,b,null), (a, null, null), (null,null,null), 当table T 容量很大的时候,在mr的过程中就会造成数据膨胀, map端的聚合将不能完成。
这个参数决定了hive是否需要增加一个mr的job。如果group set的基础远大于这个值,则hive就会添加一个附加的mr在原始的数据上,用于削减数据量。
Last updated
Was this helpful?