1.綜述
Hive的聚合函數衍生的窗口函數在我們進行數據處理和數據分析過程中起到了很大的作用
在Hive中,窗口函數允許你在結果集的行上進行計算,這些計算不會影響你查詢的結果集的行數。
Hive提供的窗口和分析函數可以分爲聚合函數類窗口函數,分組排序類窗口函數,偏移量計算類窗口函數。
本節主要介紹聚合函數類窗口函數的常見使用場景。
1.1.常見聚合類開窗函數
count() over();
sum() over();
max() over();
min() over();
avg() over();
1.2.分析函數語法
分析函數 over(partition by 列名 order by 列名 rows between 開始位置 and 結束位置)
具體解析
over()
括號內爲空時,是直接進行聚合計算。
其中partition by 列名
是按指定列進行分組,進而進行聚合計算。
最後的order by 列名
是按照指定列進行排序,進而進行聚合計算。
1.3.基礎數據準備
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求解總訪問量總和及用戶明細列表。
-- 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查詢用戶總量及用戶明細列表。
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查詢用戶最大訪問量及用戶明細
-- 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查詢用戶平均訪問量及用戶明細
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求解不同年齡段總訪問量總和及用戶明細
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求解不同客戶端總用戶數及用戶明細列表
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求解不同年齡段最大訪問量及用戶明細列表
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按性別分組截止當前年齡總訪問量及用戶明細列表
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.按性別分組截止當前年齡最大用戶訪問量及用戶明細列表
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.按性別分組截止當前年齡用戶總數
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窗口分析函數使用攻略之二-分組排序窗口函數
按例,歡迎點擊此處關注我的個人公衆號,交流更多知識。