在上一篇#HIVE 窗口函數詳解中,我們介紹了hive窗口函數的定義和語法,本篇中我們根據例子來進行實戰。
數據準備
首先我們來定義測試表結構,建立一張student_score學生分數表,主要三個欄位,學生,班級,成績,如下圖所示
接下來準備數據,為了方便,我們直接採用插入的方式,如下圖所示
最後我們的數據如下圖所示:
排序窗口
需求:求每個班級成績排名前三的學生。
row_number()函數,唯一排序,不會生成排序相同的用戶
示例和結果如下:
可以看到,一班的學生三和學生四同樣為90分的學生,會按照不同的排名進行排名。
rank()函數,不唯一排序,相同分數排名會相同,但後續排名會跳過。
示例和結果如下圖:
可以看到,一班的學生三和學生四,分數都為90分,排名都同樣為1,同時,一班的學生二為40分,排名為3,直接跳過了排名為2,所以一般沒有排名為2的學生。
dense_rank()函數,不唯一排序,排名相同的分數排序會相同,和rank()不同的時,後續排名不會跳過。
示例和結果如下圖
可以看到,一班的學生三和學生四,分數都為90分,排名並列第一,而學生二分數低於他們,排名為第二。
聚合窗口
聚合窗口能使用的有count,sum,avg,max,min。
這裡,我們以sum舉例,其他函數請舉一反三
需求: 求每個班級的學生中該學生和他上一個學號及下一個學號的學習總分。
其他類似需求,截止至當前月的銷售額,最近三個月的銷售額這種。
示例和結果如下圖
可以看到,學生一沒有學號比他低的,只有學號比他高的學生二,故總分為10+40=50分
學生二有學號比他低的學生一和學號比他高的學生三,故總分為10+40+90=140
學生四有學號比他低的學生三,學生五學號雖然比學生四高,但是屬於不同班級,故不記錄,所以最後總分為90+90=180
其他窗口
lag(col, n, DEFAULT) 用於統計窗口內向上第n行的值
lead請參考lag
需求:分班級,求上一個學號的學生成績。
示例和結果如下圖:
可以看到學生一上一個學號沒有,所以上一個分數為null
學生二上一個學生為學生一,所以上一個分數顯示10
cume_dist
計算某個窗口或分區中某個值的累積分布。假定升序排序,則使用以下公式確定累積分布:(小於等於當前值的行數) / (分區內總行數)
比如,統計小於等於當前薪水的人數,所佔總人數的比例
需求:計算班級內小於等於自己的比例
示例和結果如下圖:
如圖所示,一班一共有4個人
學生一分數最低,所以為1/4=0.25
學生二的分數為40,<=40的有學生一和學生二,所以為2/4=0.25
學生三和學生四的分數為90,最高,所以為4/4=1
ntile
作用:將分區中的數據按照順序劃分為N片,返回當前片的值。
注1:如果切片分布不均勻,默認增加第一個切片的分布注2:ntile不支持ROWS BETWEEN
需求:分班級,將數據分為2份,返回份數
示例和需求如下:
可以看到,一班一共有4個人,按照成績,10,40屬於低分區,故歸屬於第一份,90,90屬於高分區,故歸屬於第二份。
percent_rank
計算給定行的百分比排名。分組內當前行的RANK值-1/分組內總行數-1,可以用來計算超過了百分之多少的人。
需求,計算成績在班級內的百分位
示例和結果如下圖
可以看到,二班內的學生五成績最低,rank為1,(1-1)/(4-1)=0
學生六和學生七同為50分,rank為2,結果為(2-1)/(4-1)=0.33
學生八最高,rank為4,結果未(4-1)/(4-1)=1