1.综述
Hive的聚合函数衍生的窗口函数在我们进行数据处理和数据分析过程中起到了很大的作用
在Hive中,窗口函数允许你在结果集的行上进行计算,这些计算不会影响你查询的结果集的行数。
Hive提供的窗口和分析函数可以分为聚合函数类窗口函数,分组排序类窗口函数,偏移量计算类窗口函数。
本节主要介绍聚合函数类窗口函数的常见使用场景。
1.1.常见聚合类开窗函数
sql
count() over();
sum() over();
max() over();
min() over();
avg() over();
1.2.分析函数语法
sql
分析函数 over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置)
具体解析
over()
括号内为空时,是直接进行聚合计算。
其中partition by 列名
是按指定列进行分组,进而进行聚合计算。
最后的order by 列名
是按照指定列进行排序,进而进行聚合计算。
1.3.基础数据准备
sql
create table if not exists temp.user_info (
`id` bigint comment '用户id',
`client` string comment '客户端',
`gender` int comment '性别,0女1男',
`constellation` string comment '星座',
`age` int comment '年龄',
`pv` bigint comment '访问量',
`chat_num` bigint comment '聊天次数'
) comment '用户信息测试临时表'
数据预览
id | client | gender | constellation | age | pv | chat_num |
---|---|---|---|---|---|---|
1 | ios | 0 | 处女座 | 29 | 174 | 3 |
2 | ios | 1 | 双鱼座 | 26 | 263 | 2 |
3 | android | 1 | 双鱼座 | 35 | 232 | 39 |
4 | ios | 1 | 水瓶座 | 32 | 57 | 3 |
5 | ios | 1 | 射手座 | 33 | 67 | 6 |
6 | ios | 1 | 双子座 | 36 | 81 | 5 |
7 | ios | 1 | 狮子座 | 29 | 68 | 4 |
8 | ios | 1 | 狮子座 | 28 | 19 | 3 |
9 | ios | 0 | 射手座 | 32 | 479 | 2 |
10 | ios | 1 | 白羊座 | 26 | 255 | 36 |
2.over窗口为空时的计算
over()括号内为空的计算比较简单,主要应用场景为保留数据明细的同时,增加额外的列进行数据聚合计算。
1.1.sum求解总访问量总和及用户明细列表。
sql
-- over()括号内为空时,是直接进行聚合计算
select id,client,gender,age,pv,sum(pv) over() as total_pv from temp.user_info where id <= 10
order by id
数据结果
id | client | gender | age | pv | total_pv |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 1695 |
2 | ios | 1 | 26 | 263 | 1695 |
3 | android | 1 | 35 | 232 | 1695 |
4 | ios | 1 | 32 | 57 | 1695 |
5 | ios | 1 | 33 | 67 | 1695 |
6 | ios | 1 | 36 | 81 | 1695 |
7 | ios | 1 | 29 | 68 | 1695 |
8 | ios | 1 | 28 | 19 | 1695 |
9 | ios | 0 | 32 | 479 | 1695 |
10 | ios | 1 | 26 | 255 | 1695 |
可以看到给出了数据明细,并且在每行明细后增加了累积求和值。
1.2.count查询用户总量及用户明细列表。
sql
select id,client,gender,age,pv,count(id) over() as total_count from temp.user_info where id <= 10
order by id
数据结果
id | client | gender | age | pv | total_count |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 10 |
2 | ios | 1 | 26 | 263 | 10 |
3 | android | 1 | 35 | 232 | 10 |
4 | ios | 1 | 32 | 57 | 10 |
5 | ios | 1 | 33 | 67 | 10 |
6 | ios | 1 | 36 | 81 | 10 |
7 | ios | 1 | 29 | 68 | 10 |
8 | ios | 1 | 28 | 19 | 10 |
9 | ios | 0 | 32 | 479 | 10 |
10 | ios | 1 | 26 | 255 | 10 |
给出了数据明细,并且在明细后增加了当前总用户数。
1.3.max查询用户最大访问量及用户明细
sql
-- max()查询用户最大访问量及用户明细
select id,client,gender,age,pv,max(pv) over() as max_pv from temp.user_info where id <= 10
order by id
数据结果
id | client | gender | age | pv | max_pv |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 479 |
2 | ios | 1 | 26 | 263 | 479 |
3 | android | 1 | 35 | 232 | 479 |
4 | ios | 1 | 32 | 57 | 479 |
5 | ios | 1 | 33 | 67 | 479 |
6 | ios | 1 | 36 | 81 | 479 |
7 | ios | 1 | 29 | 68 | 479 |
8 | ios | 1 | 28 | 19 | 479 |
9 | ios | 0 | 32 | 479 | 479 |
10 | ios | 1 | 26 | 255 | 479 |
给出了数据明细,并在最后列增加了用户最大访问量数据
min() 同理
1.4.avg查询用户平均访问量及用户明细
sql
select id,client,gender,age,pv,avg(pv) over() as avg_pv from temp.user_info where id <= 10
order by id
数据结果
id | client | gender | age | pv | avg_pv |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 169.5 |
2 | ios | 1 | 26 | 263 | 169.5 |
3 | android | 1 | 35 | 232 | 169.5 |
4 | ios | 1 | 32 | 57 | 169.5 |
5 | ios | 1 | 33 | 67 | 169.5 |
6 | ios | 1 | 36 | 81 | 169.5 |
7 | ios | 1 | 29 | 68 | 169.5 |
8 | ios | 1 | 28 | 19 | 169.5 |
9 | ios | 0 | 32 | 479 | 169.5 |
10 | ios | 1 | 26 | 255 | 169.5 |
给出了数据明细,并在最后列增加了用户平均访问量。
2.指定列进行分组的聚合计算
2.1.sum求解不同年龄段总访问量总和及用户明细
sql
select *,sum(pv) over(partition by age) as total_pv from temp.user_info where id <= 10
order by age
数据结果
id | client | gender | age | pv | avg_pv |
---|---|---|---|---|---|
2 | ios | 1 | 26 | 263 | 518 |
10 | ios | 1 | 26 | 255 | 518 |
8 | ios | 1 | 28 | 19 | 19 |
1 | ios | 0 | 29 | 174 | 242 |
7 | ios | 1 | 29 | 68 | 242 |
4 | ios | 1 | 32 | 57 | 536 |
9 | ios | 0 | 32 | 479 | 536 |
5 | ios | 1 | 33 | 67 | 67 |
3 | android | 1 | 35 | 232 | 232 |
6 | ios | 1 | 36 | 81 | 81 |
可以看到最后的total_pv 是按照年龄段分组进行累加的
2.2.count求解不同客户端总用户数及用户明细列表
sql
select id,client,gender,age,pv,count(id) over(partition by client) as count_total from temp.user_info where id <= 10
order by id
数据结果
id | client | gender | age | pv | count_total |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 9 |
2 | ios | 1 | 26 | 263 | 9 |
3 | android | 1 | 35 | 232 | 1 |
4 | ios | 1 | 32 | 57 | 9 |
5 | ios | 1 | 33 | 67 | 9 |
6 | ios | 1 | 36 | 81 | 9 |
7 | ios | 1 | 29 | 68 | 9 |
8 | ios | 1 | 28 | 19 | 9 |
9 | ios | 0 | 32 | 479 | 9 |
10 | ios | 1 | 26 | 255 | 9 |
可以看到最后count_total 是按client分组进行计数的
2.3.max求解不同年龄段最大访问量及用户明细列表
sql
select id,client,gender,age,pv,max(pv) over(partition by age) as count_total from temp.user_info where id <= 10
order by age
数据结果
id | client | gender | age | pv | count_total |
---|---|---|---|---|---|
10 | ios | 1 | 26 | 255 | 263 |
2 | ios | 1 | 26 | 263 | 263 |
8 | ios | 1 | 28 | 19 | 19 |
7 | ios | 1 | 29 | 68 | 174 |
1 | ios | 0 | 29 | 174 | 174 |
4 | ios | 1 | 32 | 57 | 479 |
9 | ios | 0 | 32 | 479 | 479 |
5 | ios | 1 | 33 | 67 | 67 |
3 | android | 1 | 35 | 232 | 232 |
6 | ios | 1 | 36 | 81 | 81 |
可以看到进行了分组求最大值。
min以及avg同理,不再举例。
3.指定列进行分组和排序的聚合计算
3.1.sum按性别分组截止当前年龄总访问量及用户明细列表
sql
select id,client,gender,age,pv,sum(pv) over(partition by gender order by age) as total_pv from temp.user_info where id <= 10
order by gender
数据结果
id | client | gender | age | pv | total_pv |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 174 |
9 | ios | 0 | 32 | 479 | 653 |
2 | ios | 1 | 26 | 263 | 518 |
10 | ios | 1 | 26 | 255 | 518 |
8 | ios | 1 | 28 | 19 | 537 |
7 | ios | 1 | 29 | 68 | 605 |
4 | ios | 1 | 32 | 57 | 662 |
5 | ios | 1 | 33 | 67 | 729 |
3 | android | 1 | 35 | 232 | 961 |
6 | ios | 1 | 36 | 81 | 1042 |
数据解释:可以看到上述数据,性别为女的29岁及之前年龄段访问pv为174次,女性32岁及之前年龄访问总和pv为653次。
同理男性,不同年龄段及之前年龄的累加数据如上表,且相同年龄的累加值是一致的。
3.2.按性别分组截止当前年龄最大用户访问量及用户明细列表
sql
select id,client,gender,age,pv,max(pv) over(partition by gender order by age) as max_pv from temp.user_info where id <= 10
order by gender
数据明细
id | client | gender | age | pv | max_pv |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 174 |
9 | ios | 0 | 32 | 479 | 479 |
2 | ios | 1 | 26 | 263 | 263 |
10 | ios | 1 | 26 | 255 | 263 |
8 | ios | 1 | 28 | 19 | 263 |
7 | ios | 1 | 29 | 68 | 263 |
4 | ios | 1 | 32 | 57 | 263 |
5 | ios | 1 | 33 | 67 | 263 |
3 | android | 1 | 35 | 232 | 263 |
6 | ios | 1 | 36 | 81 | 263 |
可以看到男性最大访问量为263
min以及avg同理,不再举例。
3.3.按性别分组截止当前年龄用户总数
sql
select id,client,gender,age,pv,count(id) over(partition by gender order by age) as count_uv from temp.user_info where id <= 10
order by gender,age
数据结果
id | client | gender | age | pv | count_uv |
---|---|---|---|---|---|
1 | ios | 0 | 29 | 174 | 1 |
9 | ios | 0 | 32 | 479 | 2 |
2 | ios | 1 | 26 | 263 | 2 |
10 | ios | 1 | 26 | 255 | 2 |
8 | ios | 1 | 28 | 19 | 3 |
7 | ios | 1 | 29 | 68 | 4 |
4 | ios | 1 | 32 | 57 | 5 |
5 | ios | 1 | 33 | 67 | 6 |
3 | android | 1 | 35 | 232 | 7 |
6 | ios | 1 | 36 | 81 | 8 |
分组累加求和
综合以上内容,第一部分和第二部分可以通过聚合函数+join的形式实现,但第三部分排序累加计数,实现起来比较困难,而这部分在一些需要分组累加汇总的场景使用很方便。
下一期:hive窗口分析函数使用攻略之二-分组排序窗口函数
按例,欢迎点击此处关注我的个人公众号,交流更多知识。