grouping_id&grouping sets

grouping sets 用法
在Hive中,会出现对同一个数据表进行不同粒度的汇总,这时可以有两种方案:

用多个sql,对不同粒度使用不同的 group by 方法。
用1个sql,使用 grouping sets 方法一次性得到所有粒度的汇总。
以测试数据表 tmp_student 为例:

1、生成测试数据

在 hive 环境中创建临时表:

create table tmp.tmp_student
(
   name string,
   class int,
   sex string,
   score int
)
row format delimited fields terminated by '|';

然后加载测试数据:

load data local inpath 'text.txt' into table tmp_student;

其中,text.txt 内容如下:

A|3|男|45
B|3|女|55
C|2|女|74
D|3|男|90
E|1|男|80
F|2|女|92
G|1|女|95
H|1|男|95
I|3|女|99
J|3|男|99

查看是否加载成功:

hive> select * from tmp_student;
OK
A	345
B	355
C	274
D	390
E	180
F	292
G	195
H	195
I	399
J	399
Time taken: 0.377 seconds, Fetched: 10 row(s)

2、grouping sets示例

数据表有4个字段:姓名、班级、性别、分数。
如果我想按照以下3个粒度汇总:
1、每个班级的平均分数
2、每个性别的平均分数
3、每个班级下不同性别的平均分数
则使用多个sql分别汇总的方案为:

select class, avg(score) from tmp.tmp_student group by class;
select sex, avg(score) from tmp.tmp_student group by sex;
select class, sex, avg(score) from tmp.tmp_student group by class, sex;

而使用1个sql使用grouping sets的方案为:

select
    grouping__id, -- 内置变量,只要使用grouping sets就可以调用
    class,
    sex,
    avg(score) as avg_score
from
    tmp.tmp_student
group by
    class,
    sex 
grouping sets(
    class, 
    sex,
    (class, sex)
) order by 
    grouping__id

此处结果和原文章不同(https://blog.csdn.net/HappyRocking/article/details/106545559)

结果为:

OK
0       378.0
0       377.0
0       283.0
0       187.5
0       195.0
1       3       NULL    77.6
1       2       NULL    83.0
1       1       NULL    90.0
2       NULL81.8
2       NULL83.0

可以看到,使用 grouping sets 同时汇总出了 3 种不同粒度的平均分数。
注意:
1、grouping sets 只能用于 group by 之后。
2、grouping sets 中可以包含多种粒度,粒度之间用逗号连接。
3、grouping sets 中的所有字段,都必须出现在 group by 中,相当于 group by 后面的字段是最细粒度。
4、如果 select 中的字段,没有包含在某个 grouping set 中,那么这个粒度下的这个字段值为 NULL。
4、不同的粒度,可以使用内置变量 grouping__id 进行区分。

本文重点:

3、grouping_id计算方法

grouping sets 中的每一种粒度,都对应唯一的 grouping__id 值,其计算公式与 group by 的顺序、当前粒度的字段有关。
具体计算方法如下:

① 将 group by 的所有字段 倒序 排列。
② 对于每个字段,如果该字段出现在了当前粒度中,则该字段位置赋值为0,否则为1。
③ 这样就形成了一个二进制数,这个二进制数转为十进制,即为当前粒度对应的 grouping__id。

以上述对 tmp_student 的3种粒度的统计结果为例:

序号grouping set给排列的字段(sex class)为null的赋值对应的十进制(grouping__id 的值)
1class011
2sex102
3class,sex000

4、再验证

新增name 维度

select
    grouping__id, -- 内置变量,只要使用grouping sets就可以调用
    name ,
    class,
    sex,
    avg(score) as avg_score
from
    tmp.tmp_student
group by
    name ,
    sex ,
    class
grouping sets(
    name ,
    class,
    sex,
    (class, sex),
    (name, sex)
) order by
    grouping__id
;

结果:

1       E       NULL80.0
1       G       NULL95.0
1       D       NULL90.0
1       H       NULL95.0
1       C       NULL74.0
1       J       NULL99.0
1       B       NULL55.0
1       F       NULL92.0
1       A       NULL45.0
1       I       NULL99.0
3       C       NULL    NULL    74.0
3       J       NULL    NULL    99.0
3       I       NULL    NULL    99.0
3       H       NULL    NULL    95.0
3       G       NULL    NULL    95.0
3       F       NULL    NULL    92.0
3       E       NULL    NULL    80.0
3       D       NULL    NULL    90.0
3       B       NULL    NULL    55.0
3       A       NULL    NULL    45.0
4       NULL    378.0
4       NULL    187.5
4       NULL    377.0
4       NULL    283.0
4       NULL    195.0
5       NULL    NULL81.8
5       NULL    NULL83.0
6       NULL    3       NULL    77.6
6       NULL    2       NULL    83.0
6       NULL    1       NULL    90.0
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值