【Hive】hive窗口函數/分析函數 over子句

over子句介紹

over子句參考鏈接 https://blog.csdn.net/czr11616/article/details/101645693

1. 什麼是over子句

我們可以形象的把over()子句理解成開窗子句,即打開一個窗口,窗口內包含多條記錄,over()會給每一行開一個窗口。如下圖,總共有5條記錄,每一行代表一條記錄,over()在每一條記錄的基礎上打開一個窗口,給r1記錄打開w1窗口,窗口內只包含自己,給r2打開w2窗口,窗口內包含r1、r2,給r3打開w3窗口,窗口內包含r1、r2、r3,以此類推…
在這裏插入圖片描述
由上我們不難發現,在使用over()子句進行查詢的時候, 不僅可以查詢到每條記錄的信息,還可以查詢到這條記錄對應窗口內的所有記錄的聚合信息,所以我們通常結合聚合函數和over()子句一起使用。

那麼over()是如何進行開窗的呢?即每條記錄對應的窗口內應該包含哪些記錄呢?這些都是在over()子句的括號內進行定義。

2. over子句的開窗範圍

在這裏插入圖片描述

  • current row代表查詢的當前行
  • 1 preceding代表前一行
  • 1 following代表後一行
  • unbounded preceding代表第一行
  • unbounded following代表最後一行。

(注意這裏的第一行和最後一行並不是嚴格的第一行和最後一行,根據具體情況而定)

3. window clause

over()子句的開窗範圍可以通過window 子句(window clause)在over()的括號中定義,window clause的規範如下:

(ROWS | RANGE) BETWEEN (UNBOUNDED | [num]) PRECEDING AND ([num] PRECEDING | CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
(ROWS | RANGE) BETWEEN CURRENT ROW AND (CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
(ROWS | RANGE) BETWEEN [num] FOLLOWING AND (UNBOUNDED | [num]) FOLLOWING

例如 :

select *,sum(column_name) over( rows between unbounded preceding and unbounded following) from table_name 

表示查詢每一行的所有列值,同時給每一行打開一個從第一行到最後一行的窗口,並統計窗口內所有記錄的column_name列值的和。最後給每一行輸出該行的所有屬性以及該行對應窗口內記錄的聚合值。

4. over子句默認值

如果over()子句中什麼都不寫的話,默認開窗範圍是:rows between unbounded preceding and unbounded following

4.1 order by

如果over()子句中接order by,例如:over(order by date),
則默認的開窗範圍爲根據date排序後的rows between unbounded preceding and current row,
即第一行到當前行,
意思是over(order by date)over(order by date rows between unbounded preceding and current row)的效果是一樣的。

4.2 partition by

如果over子句中接partition by(和group by類似,都是根據列值對行進行分組),
例如over(partition by month(date)),
則每一行的默認的開窗範圍爲當前行所在分組的所有記錄。
注意partition by子句不能單獨和window clause子句一起使用,必須結合order by子句,下面會討論。

4.3 partition by + order by

先分組,再排序,即組內排序。
同樣的,如果 order by後不接window clause,則每一行的默認的開窗範圍爲:當前行所在分組的第一行到當前行,
即over(partition by (month(date)) order by orderdate)over(partition by (month(date)) order by orderdate rows between undounded preceding and current row)是一樣的。

幾個常用開窗函數

案例引出

有學生信息表:

hive> select * from stu_managed;
OK
1		張三dg	un	23	IS
95002	劉晨		女	19	IS
95017	王風娟	女	18	IS
95018	王一		女	19	IS
95013	馮偉		男	21	CS
95014	王小麗	女	19	CS
95019	邢小麗	女	19	IS
95020	趙錢		男	21	IS
95003	王敏		女	22	MA
95004	張立		男	19	IS
95012	孫花		女	20	CS
95010	孔小濤	男	19	CS
95005	劉剛		男	18	MA
95006	孫慶		男	23	CS
95007	易思玲	女	19	MA
95008	李娜		女	18	CS
95021	週二		男	17	MA
95022	鄭明		男	20	MA
95001	李勇		男	20	CS
95011	包小柏	男	18	MA
95009	夢圓圓	女	18	MA
95015	王君		男	18	MA

求:學生信息表中 每個部門中年齡最大的前兩個
分析:
將數據按照部門分組
在在每一個部門中進行局部排序 倒序
每個部門中輸出2個

直接寫比較困難,藉助分析函數
窗口函數+over子句

over子句: 用於指定分組(分區)或排序規則的 行號|排名規則

#over子句中的語法:
over(distribute by + sort by )
over(partition by + order by )

row_number

  1. 對學生信息數據 按照部門分 在每個部門中加行號

    hive> select
        > dept,name,row_number() over(distribute by dept)
        > from stu_managed;
    Total MapReduce CPU Time Spent: 0 msec
    OK
    CS	孫慶		1
    CS	馮偉		2
    CS	王小麗	3
    CS	李勇		4
    CS	孫花		5
    CS	孔小濤	6
    CS	李娜		7
    IS	張三dg	1
    IS	張立		2
    IS	趙錢		3
    IS	邢小麗	4
    IS	王一		5
    IS	王風娟	6
    IS	劉晨		7
    MA	夢圓圓	1
    MA	王君		2
    MA	易思玲	3
    MA	劉剛		4
    MA	週二		5
    MA	鄭明		6
    MA	包小柏	7
    MA	王敏		8
    Time taken: 1.959 seconds, Fetched: 22 row(s)
    
  2. 相對每一個部門的每個人的年齡排序

    hive> select
        > dept,name,age,row_number() over(distribute by dept sort by age desc)
        > from stu_managed;
    Total MapReduce CPU Time Spent: 0 msec
    OK
    CS	孫慶		23	1
    CS	馮偉		21	2
    CS	李勇		20	3
    CS	孫花		20	4
    CS	王小麗	19	5
    CS	孔小濤	19	6
    CS	李娜		18	7
    IS	張三dg	23	1
    IS	趙錢		21	2
    IS	王一		19	3
    IS	劉晨		19	4
    IS	張立		19	5
    IS	邢小麗	19	6
    IS	王風娟	18	7
    MA	王敏		22	1
    MA	鄭明		20	2
    MA	易思玲	19	3
    MA	夢圓圓	18	4
    MA	包小柏	18	5
    MA	劉剛		18	6
    MA	王君		18	7
    MA	週二		17	8
        
    

rank

  1. 在每個部門中按照年齡進行添加排名
hive> select
    > dept,name,age,rank() over(partition by dept order by age)
    > from stu_managed;
Total MapReduce CPU Time Spent: 0 msec
OK
CS	李娜		18	1
CS	孔小濤	19	2
CS	王小麗	19	2
CS	李勇		20	4
CS	孫花		20	4
CS	馮偉		21	6
CS	孫慶		23	7
IS	王風娟	18	1
IS	張立		19	2
IS	劉晨		19	2
IS	王一		19	2
IS	邢小麗	19	2
IS	趙錢		21	6
IS	張三dg	23	7
MA	週二		17	1
MA	劉剛		18	2
MA	包小柏	18	2
MA	夢圓圓	18	2
MA	王君		18	2
MA	易思玲	19	6
MA	鄭明		20	7
MA	王敏		22	8

dense_rank

dense_rank 與 rank的區別是不會累加並列

hive> select dept,name,age,dense_rank() over(partition by dept order by age) from stu_managed;
Total MapReduce CPU Time Spent: 0 msec
OK
CS	李娜		18	1
CS	孔小濤	19	2
CS	王小麗	19	2
CS	李勇		20	3
CS	孫花		20	3
CS	馮偉		21	4
CS	孫慶		23	5
IS	王風娟	18	1
IS	張立		19	2
IS	劉晨		19	2
IS	王一		19	2
IS	邢小麗	19	2
IS	趙錢		21	3
IS	張三dg	23	4
MA	週二		17	1
MA	劉剛		18	2
MA	包小柏	18	2
MA	夢圓圓	18	2
MA	王君		18	2
MA	易思玲	19	3
MA	鄭明		20	4
MA	王敏		22	5

row_number rank dense_rank 使用場景:結合over子句 MR中分組求topN

案例答案

hive> select * from (select dept,name,age,row_number() over(distribute by dept sort by age desc) index from stu_managed) a where index<=2;
Total MapReduce CPU Time Spent: 0 msec
OK
CS	孫慶		23	1
CS	馮偉		21	2
IS	張三dg	23	1
IS	趙錢		21	2
MA	王敏		22	1
MA	鄭明		20	2

發佈了84 篇原創文章 · 獲贊 12 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章