Hive第七天——Hive函數(開窗函數之組內排序)


本文部分參考自:https://blog.csdn.net/qq_23897391/article/details/100688796


Hive第七天——Hive函數

自己的話:千里之行,始於足下。

每天都要保持前進,我勢必要有強勁的實力,再跟明天的自己問好。

開窗函數:組內排序


開窗函數的固定寫法:

over(partition by 列名1,列名2 …… order by 列名3,列名4 …… [desc])

數據準備:

新建test.txt文件,輸入如下的三列數據,以空格分隔。第一列是月份,第二列代表商鋪名稱,第三列代表該商鋪該月營業額(萬元)。

[root@hadoop ~]# vim test.txt 
 
2019-01 a 4
2019-01 b 3
2019-01 c 3
2019-01 d 2
2019-01 e 1
2019-02 a 1
2019-02 b 2
2019-02 c 3
2019-02 d 3
2019-02 e 4

在hive中新建表temp_test10,將test文件中的數據插入,查看數據。

hive >CREATE TABLE temp_test10 (
     >month STRING comment '月份',
     >shop STRING comment '商鋪名稱',
     >money STRING comment '營業額(萬元)') 
     >row format delimited 
     >fields terminated BY ' ';
 
 
hive >load data local inpath '/root/test.txt' into table temp_test10;
 
hive >select * from temp_test10;
 
temp_test10.month	temp_test10.shop	temp_test10.money
2019-01					a					4
2019-01					b					3
2019-01					c					3
2019-01					d					2
2019-01					e					1
2019-02					a					1
2019-02					b					2
2019-02					c					3
2019-02					d					3
2019-02					e					4

一、row_number()

row_number()會生成數據項在分組中的排名,排名即便相等也不會有並列排名,相同排名隨機排序。

舉例:

1.生成排序後的唯一序號

首先按照月份進行分組,然後每個組內按照營業額從大到小排序,爲組內每一行數據得到一個唯一序號。

hive >SELECT month,shop,MONEY,row_number() 
	 >OVER (PARTITION BY month ORDER BY 	MONEY DESC --按照月份進行分組,然後每個組內按照營業額從大到小排序) 
	 >AS rk  --生成的排序序號
	 >FROM temp_test10
 
 
結果:
 
month	shop	money	rk
2019-01	 a		4  	     1
2019-01	 c		3		 2
2019-01	 b		3		 3
2019-01	 d 		2		 4
2019-01	 e		1		 5
2019-02	 e 		4		 1
2019-02	 d		3		 2
2019-02	 c		3		 3
2019-02	 b		2		 4
2019-02	 a		1		 5

2.取top n

取出1月和2月每個月營業額排名前3的店鋪及營業額。

使用子查詢取出rk<=3的數據即可
 
hive >SELECT *
	 >FROM (SELECT month,shop,MONEY,row_number() 
	 >OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份進行分組,然後每個組內按照營業額從大到小排序) 
	 >AS rkFROM temp_test10) a
	 >WHERE rk <= 3;
 
結果:
a.month	a.shop	a.money	a.rk
2019-01	a	4	1
2019-01	c	3	2
2019-01	b	3	3
2019-02	e	4	1
2019-02	d	3	2
2019-02	c	3	3

如果只有一個分組,那麼可以省略partition by,比如只取出1月營業額排名前3的店鋪及營業額。

hive >SELECT *
	 >FROM (SELECT month,shop,MONEY,row_number() 
	 >OVER (ORDER BY MONEY DESC --按照營業額從大到小排序) 
	 >AS rkFROM temp_test10WHERE month = '2019-01') a
	 >WHERE rk <= 3;
 
結果:
a.month	a.shop	a.money	a.rk
2019-01	a	4	1
2019-01	c	3	2
2019-01	b	3	3

3.每個分組內取出n個隨機值

row_number()配合rand()函數即可實現每個分組內取出n個隨機值的需求。
每個月隨機抽取兩家店鋪:

hive >SELECT *
	 >FROM (SELECT month,shop,MONEY,row_number() 
	 >OVER (PARTITION BY month ORDER BY rand(1) --可以使用任意數作爲種子進行隨機排序,也可以不填,直接使用rand()) 
	 >AS rk FROM temp_test10) a
	 >WHERE rk <= 2; --限制rk來取出n個隨機值
 
結果:
a.month	a.shop	a.money	a.rk
2019-01	c	3	1
2019-01	d	2	2
2019-02	a	1	1
2019-02	e	4	2

二、rank()

rank()可以生成數據項在分組中的排名,排名相等時會產生並列排名,然後會在名次中留下空位。應用場景不多,很少需要使用,瞭解即可。

舉例:

首先按照月份進行分組,然後每個組內按照營業額從大到小排序,生成排名,並列排名後留下空位。

hive >SELECT month,shop,MONEY,rank() 
	 >OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份進行分組,然後每個組內按照營業額從大到小排序) 
	 >AS rk  --生成的排序序號
	 >FROM temp_test10;
 
 
結果:
 
month	shop	money	rk
2019-01	 a		 4		1
2019-01	 c		 3		2
2019-01	 b		 3		2
2019-01	 d		 2		4
2019-01	 e		 1		5
2019-02	 e	  	 4		1
2019-02	 d		 3		2
2019-02	 c		 3		2
2019-02	 b		 2		4
2019-02	 a 		 1		5

三、 dense_rank()

dense_rank()可以生成數據項在分組中的排名,排名相等時會產生並列排名,但不會在名次中留下空位。應用場景也不多,很少需要使用,瞭解即可

舉例:

首先按照月份進行分組,然後每個組內按照營業額從大到小排序,生成排名,並列排名後不要留下空位。

hive >SELECT month,shop,MONEY,dense_rank() 
	 >OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份進行分組,然後每個組內按照營業額從大到小排序) 
	 >AS rk  --生成的排序序號
	 >FROM temp_test10;
 
 
結果:
 
month	shop	money	rk
2019-01	 a	   4		1
2019-01	 c	   3		2
2019-01	 b	   3		2
2019-01	 d	   2		3
2019-01	 e	   1		4
2019-02	 e	   4		1
2019-02	 d	   3		2
2019-02	 c	   3		2
2019-02	 b	   2		3
2019-02	 a	   1		4

四、綜合案例

最後,再拿出一個我自己的舉例:

求每個人前兩高的分數

1.數據準備

vi score.txt

zhangsan,1,90,2
zhangsan,2,95,1
zhangsan,3,68,3
lisi,1,88,3
lisi,2,95,2
lisi,3,98,1

2.導入數據

hive >create table t_score(name string,kcid string,score int)
	 >row format delimited
	 >fields terminated by ',';

hive>load data local inpath '/home/score.txt' into table t_score;

3.查詢數據

(1)按名字分組並在組內排序展示序號
hive> select *,row_number() over(partition by name order by score desc) rank from t_score;

在這裏插入圖片描述

(2)從上表中再查詢排名小於三的數據
hive >select name,kcid,score
	 >from(select *,row_number() over(partition by name order by score desc) as rank from t_score) tmp
	 >where rank<3;

在這裏插入圖片描述

4.最後,應用到之前的json電影評分數據上

求出每個用戶評分最高的3部電影

建表並加載數據
hive >create table t_rate_topn_uid
	 >as
	 >select uid,movie,rate,ts
	 >from(select *,row_number() over(partition by uid order by rate desc) as rank from t_rate) tmp
	 >where rank<11;


查詢
hive> select * from t_rate_topn_uid where uid=1;

在這裏插入圖片描述


這樣,開窗函數中的組內排序就介紹完了,希望對大家有所幫助,可別忘了點贊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章