hive-窗口函數

1 窗口函數語法

分析函數/專用窗口函數 over(partition by 列名 order by 列名 rows between 開始位置 and
結束位置)

常用的分析函數

常用的分析函數:sum()、max()、min()、avg()、count()

常用的專用窗口函數

專用窗口函數:row_number()、rank()、dense_rank()

窗口函數

窗口函數的3個組成部分可以單獨使用,也可以混合使用,也可以全部不用

over(partition by 列名 order by 列名 rows between 開始位置 and 結束位置)

partition by

對指定的字段進行分組,后續都會以組為單位,把每個分組單獨作為一個窗口進行統計分析操作。

案例 01:對窗口中的數據求和,并把求和結果分別分發到對應窗口的每一條數據中

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over(partition by col1) as '對窗口中的數據求和'
from temp
輸出結果:
col     對窗口中的數據求和
A       2
A       2
B       1

案例 02:對整體數據求和,并把求和結果分發到每一條數據中

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over() as '對整體數據求和'
from temp
輸出結果:
col     對整體數據求和
A       3
A       3
B       3

order by

order by 與 partition by 連用的時候,可以對各個分組內的數據,按照指定的字段進行排序。如果沒有 partition by 指定分組字段,那么會對全局的數據進行排序。

案例 01:對數據進行全局排序

with temp as(
select 'A' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select col1,row_number() over(order by col1 desc) as 排序 from temp
輸出結果:
col1     排序 
C        1
C        2
B        3
A        4

案例 02:當排序的維度不存在重復的情況下,即 order by 指定的字段,使用 order by + 分析函數 sum(),可以產生求整體累計數的效果。

with temp_01 as(
select 'A' as col1,1 as col2
union all 
select 'D' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select col1,sum(col2) over(order by col1) as 求累計 from temp_01
輸出結果:
col1    求累計
A       1
B       2
C       3
D       4

但是當 order by 指定的字段,數據存在重復的時候,會在不重復的數據中產生累計效果,重復的數據中,會把整體的累計結果分發到每條重復的數據中。

with temp_02 as(
select 'A' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select col1,sum(col2) over(order by col1) as 求累計 from temp_02
輸出結果:
col1    求累計
A       1
B       2
C       4
C       4

案例 03:當排序的維度不存在重復的情況下,即 order by 指定的字段,parition by 與 order by 連用,并使用分析函數 sum() ,可以產生求窗口中累計數的效果。

with temp_01 as(
select 'A' as col1,'b' as col2,1 as col3
union all 
select 'A' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'b' as col2,1 as col3
)select col1,sum(col3) over(partition by col1 order by col1,col2) as 求累計 from temp_01
輸出結果:
col1     求累計
A        1
A        2
C        1
C        2

但是當 order by 指定的字段組合,數據存在重復的時候,會在不重復的數據中產生累計效果,而重復的數據中,也是會把整體的累計結果分發到每條重復的數據中,如下,用 col1 和 col2 排序。

with temp_02 as(
select 'A' as col1,'b' as col2,1 as col3
union all 
select 'A' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'a' as col2,1 as col3
)select col1,sum(col3) over(partition by col1 order by col1,col2) as 求累計 from temp_02
輸出結果:
col1     求累計
A        1
A        2
C        2
C        2

rows between 開始位置 and 結束位置

rows between 是用來劃分窗口中,函數發揮作用的數據范圍。我們用如下例子加深 rows between 的理解。
在這里插入圖片描述

在A分組中,計算第2行,第2列的值的時候,會從窗口起點(第2行,第2列),計算到當前行(第2行,第2列)。結果是1。
在A分組中,計算第3行,第2列的值的時候,會從窗口起點(第2行,第2列),計算到當前行(第3行,第2列)。結果是2。

rows between 常用的參數如下:

① n preceding:往前

② n following:往后

③ current row:當前行

④ unbounded:起點(一般結合preceding,following使用)

a. unbounded preceding:表示該窗口最前面的行(起點) b. unbounded
following:表示該窗口最后面的行(終點)

使用例子如下:

rows between unbounded preceding and current row(表示從起點到當前行的數據進行) rows
between current row and unbounded following(表示當前行到終點的數據進行) rows
between unbounded preceding and unbounded following (表示起點到終點的數據) rows
between 1 preceding and 1 following(表示往前1行到往后1行的數據) rows between 1
preceding and current row(表示往前1行到當前行)

rows between unbounded preceding and current row與 partition by 、order by 連用,可以產生對窗口中的數據求累計數的效果。

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over(partition by col1 order by col2 desc rows between unbounded preceding and current row) as '對窗口中的數據求和'
from temp
輸出結果:
col1     對窗口中的數據求和
A        1
A        2
B        1
  1. 排序窗口函數
    2.1 排序并產生自增編號,自增編號不重復且連續
    我們可以使用函數:row_number() over()

數據樣例:

col1                             ranks
a            1
b              2
b              3
b              4
c              5
d              6具體語法如下:> row_number() over(partition by 列名 order by 列名 rows between 開始位置 and
> 結束位置)案例如下:>with temp as(
select 'a' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'c' as col1
union all 
select 'd' as col1
)
>
>select col1,row_number() over(order by col1) as ranks from temp
輸出結果:
col1     rank
a        1
b        2
b        3
b        4
c        5
d        6

2.2 排序并產生自增編號,自增編號會重復且不連續
我們可以使用函數:rank() over()

數據樣例:

col1     ranks
a        1
b        2
b        2
b        2
c        5
d        6

具體語法如下:

rank() over(partition by 列名 order by 列名 rows between 開始位置 and 結束位置)

案例如下:

with temp as(
select 'a' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'c' as col1
union all 
select 'd' as col1
)select col1,rank() over(order by col1) as ranks from temp
輸出結果:
col1     rank
a        1
b        2
b        2
b        2
c        5
d        6

2.3 排序并產生自增編號,自增編號會重復且連續
我們可以使用函數:dense_rank() over()

數據樣例:

col1     ranks
a        1
b        2
b        2
b        2
c        3
d        4

具體語法如下:

dense_rank() over(partition by 列名 order by 列名 rows between 開始位置 and
結束位置)

案例如下:

with temp as(
select 'a' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'c' as col1
union all 
select 'd' as col1
)select col1,dense_rank() over(order by col1) as ranks from temp	
輸出結果:
col1     ranks
a        1
b        2
b        2
b        2
c        3
d        4

聚合窗口函數

3.1 求窗口中的累計值
我們可以使用:sum() over()

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over(partition by col1 order by col2 desc rows between unbounded preceding and current row) as '對窗口中的數據求和'
from temp
輸出結果:
col1     對窗口中的數據求和
A        1
A        2
A        3
B        1
B        1

3.2 求窗口中 3 天的平均價格
我們可以使用 avg() over()

with temp as(
select 'A' as col1,'2022-11-01' as date_time,50 as price
union all 
select 'A' as col1,'2022-11-02' as date_time,60 as price
union all 
select 'A' as col1,'2022-11-03' as date_time,45 as price
union all 
select 'A' as col1,'2022-11-04' as date_time,70 as price
union all 
select 'A' as col1,'2022-11-05' as date_time,40 as price
union all 
select 'A' as col1,'2022-11-06' as date_time,40 as price
union all 
select 'B' as col1,'2022-11-01' as date_time,40 as price
union all 
select 'B' as col1,'2022-11-02' as date_time,30 as price
union all 
select 'B' as col1,'2022-11-03' as date_time,50 as price
union all 
select 'B' as col1,'2022-11-04' as date_time,50 as price
)select
col1
,date_time
,price
,avg(price) over(partition by col1 order by date_time rows between 2 preceding and current row) as '3天的平均價格'
from temp輸出結果:
col1      date_time        price      3天的平均價格
A         2022-11-01       50         50
A         2022-11-02       60         55
A         2022-11-03       45         51.666666666666664
A         2022-11-04       70         58.333333333333336
A         2022-11-05       40         51.666666666666664
A         2022-11-06       40         50
B         2022-11-01       40         40
B         2022-11-02       30         35
B         2022-11-03       50         40
B         2022-11-01       50         43.333333333333336

3.3 求分組中的最大值/最小值

with temp_01 as(
select 'A' as col1,10 as col2
union all 
select 'C' as col1,10 as col2
union all 
select 'C' as col1,20 as col2
union all 
select 'A' as col1,20 as col2
union all
select 'A' as col1,20 as col2
)select
col1
,col2
,max(col2) over(partition by col1) as 窗口中的最大值
,min(col2) over(partition by col1) as 窗口中的最小值
from temp_01輸出結果:
col1     col2     窗口中的最大值     窗口中的最小值
A        10       20                 10
A        20       20                 10
A        20       20                 10
C        10       20                 10
C        20       20                 10

3.4 求分組中的總記錄數

with temp_01 as(
select 'A' as col1,'a' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'A' as col1,'b' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,col2
,count(col2) over(partition by col1) as 分組中的記錄數
from temp_01輸出結果:
col1     col2     分組中的記錄數
A        a        3
A        b        3
A        b        3
C        a        2
C        a        2
  1. 位移窗口函數
    4.1 獲取分組中往前 n 行的值
    基礎語法:

lead(field,n,default_value) over()

語法解析:

  1. field 是指定的列名

  2. n 是往前的行數

  3. 行往前導致的,最后的 n 行值為 null,可以用 default_value 代替。

使用案例:

with temp_01 as(
select 'A' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-02' as date_time
union all 
select 'A' as col1,'2022-12-02' as date_time
union all
select 'A' as col1,'2022-12-03' as date_time
)select
col1
,date_time
,lead(date_time,1,'2022-12-30') over(partition by col1 order by date_time) as 往前n行的值 
from temp_01輸出結果:
col1     date_time     往前n行的值
A        2022-12-01    2022-12-02
A        2022-12-02    2022-12-03
A        2022-12-03    2022-12-30
C        2022-12-01    2022-12-02
C        2022-12-02    2022-12-30

4.2 獲取分組中往后 n 行的值
基礎語法:

lag(field,n, default_value) over()

語法解析:

  1. field 是指定的列名

  2. n 是往前的行數

  3. 行往后導致的,前面的 n 行值為 null,可以用 default_value 代替。

使用案例:

with temp_01 as(
select 'A' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-02' as date_time
union all 
select 'A' as col1,'2022-12-02' as date_time
union all
select 'A' as col1,'2022-12-03' as date_time
)select
col1
,date_time
,lag(date_time,1,'2022-12-30') over(partition by col1 order by date_time) as 往前n行的值 
from temp_01輸出結果:
col1      date_time     往前n行的值
A         2022-12-01    2022-12-30
A         2022-12-02    2022-12-01
A         2022-12-03    2022-12-02
C         2022-12-01    2022-12-30
C         2022-12-02    2022-12-01

極值窗口函數

5.1 獲取分組內第一行的值
我們可以使用 first_value(col,true/false) over(),作用是:取分組內排序后,截止到當前行,第一個值。

注意:

當第二個參數為 true 的時候,會跳過空值 當 over() 中不指定排序的時候,會默認使用表中數據的原排序。
案例:將每行數據換成當前窗口指定字段的第一個值

with temp_01 as(
select 'A' as col1,'b' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'b' as col2
union all 
select 'A' as col1,'a' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,first_value(col2) over(partition by col1 order by col2) as 第一個值 
from temp_01
輸出結果:
col1     第一個值
A        a
A        a
A        a
C        a 
C        a
select
col1
,first_value(col2) over(partition by col1) as 第一個值 
from temp_01
輸出結果:
col1     第一個值
A        b
A        b
A        b
C        a
C        a

5.2 獲取分組內最后一行的值
我們可以使用 last_value(col,true/false) over(),作用是:取分組內排序后,截止到當前行,最后一個值。所以,如果使用 order by 排序的時候,想要取最后一個值,需要與 rows between unbounded preceding and unbounded following 連用。

注意:

當第二個參數為 true 的時候,會跳過空值 當 over() 中不指定排序的時候,會默認使用表中數據的原排序。 當 over()
中指定排序的時候,要與 rows between unbounded preceding and unbounded following
連用

with temp_01 as(
select 'A' as col1,'b' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'b' as col2
union all 
select 'A' as col1,'a' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,last_value(col2) over(partition by col1 order by col2 rows between unbounded preceding and unbounded following) as 第一個值 
from temp_01輸出結果:
col1       第一個值
A          b
A          b
A          b
C          b
C          b

相信大家都發現了,在本案例中,我們使用 order by 的時候與 rows between unbounded preceding and unbounded following 連用了,這是需要注意的一個點,如果不連用,將會產生以下效果:

with temp_01 as(
select 'A' as col1,'b' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'b' as col2
union all 
select 'A' as col1,'a' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,last_value(col2) over(partition by col1 order by col2) as 第一個值 
from temp_01輸出結果:
col1      第一個值
A         a
A         b
A         b
C         a
C         b
  1. 分箱窗口函數
    ntile() over() 分箱窗口函數,用于將分組數據按照順序切分成 n 片,返回當前切片值,如果切片不均勻,默認增加到第一個切片中。

案例:查詢成績前 20% 的人。

with temp as(
select 'A' as col1,90 as grade
union all 
select 'B' as col1,80 as grade
union all
select 'C' as col1,82 as grade
union all
select 'D' as col1,99 as grade
union all 
select 'E' as col1,100 as grade
union all 
select 'F' as col1,92 as grade
union all
select 'G' as col1,93 as grade
union all
select 'H' as col1,85 as grade
union all
select 'I' as col1,95 as grade
union all
select 'J' as col1,70 as grade
)select 
col1
,grade
from(selectcol1,grade,ntile(5) over(order by grade desc) as levelfrom temp)t1
where t1.level = 1輸出結果:
col1     grade
E        100
D        99

轉載:https://zhuanlan.zhihu.com/p/587440793

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/214971.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/214971.shtml
英文地址,請注明出處:http://en.pswp.cn/news/214971.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【簡易版】Linux下Protobuf 實現網絡版通訊錄--C++

一、介紹 該項目的主要目的是用于熟悉protobuf的使用,體驗數據在網絡中序列化反序列化的形式,并非一個完整的項目。 該通訊錄只實現了增加聯系人的功能。服務器端接收到請求后會將聯系人的信息打印。 二、環境搭建 使用Httplib庫,可以快速…

jsp文件引用的css修改后刷新不生效問題

問題 在對 JavaWeb 項目修改的過程中,發現修改了 jsp 文件引入的 css 文件的代碼后頁面的樣式沒有更新的問題。 原因 導致這個問題的原因可能是因為瀏覽器緩存的問題。 解決方法 下面介紹兩種解決方法,供大家參考: 1、給 link 標簽的 c…

TrustZone之安全虛擬化

在Armv7-A首次引入虛擬化時,它僅在非安全狀態中添加。在Armv8.3之前,Armv8也是如此,如下圖所示: 如前所述在切換安全狀態時,EL3用于托管固件和安全監視器。安全EL0/1托管受信任的執行環境(TEE),由受信任的服務和內核組成。 在安全狀態下,沒有對多個虛擬機的需…

Java基礎——什么是main方法

main方法是Java虛擬機調用的入口,該方法的權限必須是public,Java虛擬機在執行main方法時不必創建對象,所以該方法是static修飾,接收一個String類型的數組參數,數組保存執行Java命令時傳遞給所運行的類的參數&#xff0…

基于微信小程序和Spring、SpringMVC、MyBatis的汽車租賃管理系統

文章目錄 項目介紹主要功能截圖:部分代碼展示設計總結項目獲取方式?? 作者主頁:超級無敵暴龍戰士塔塔開 ?? 簡介:Java領域優質創作者??、 簡歷模板、學習資料、面試題庫【關注我,都給你】 ??文末獲取源碼聯系?? 項目介紹 基于微信小程序和Spring、SpringMVC、My…

Kafka生產問題總結及性能優化實踐

1、消息丟失情況 消息發送端: (1)acks0: 表示producer不需要等待任何broker確認收到消息的回復,就可以繼續發送下一條消息。性能最高,但是最容易丟消息。大數據統計報表場景,對性能要求很高&am…

JavaCV之rtmp推流(FLV和M3U8)

JavaCV與FFmpeg FFmpeg是一款開源的多媒體處理工具集,它包含了一系列用于處理音頻、視頻、字幕等多媒體數據的庫和工具。 JavaCV集成了FFmpeg庫,使得Java開發者可以使用FFmpeg的功能,比如視頻解碼、編碼、格式轉換等。 除了FFmpeg&#xff0…

LeetCode力扣每日一題(Java):35、搜索插入位置

一、題目 二、解題思路 1、我的思路(又稱:論API的重要性) 讀完題目之后,我心想這題目怎么看著這么眼熟?好像我之前學過的一個API呀! 于是我回去翻了翻我之前寫的博客:小白備戰藍橋杯&#xf…

通用的AGI 安全風險

傳統安全風險 平臺基礎設施安全風險 模型與數據層安全風險 應用層安全風險 平臺基礎設施安全風險 (1)物理攻擊:機房管控不到位 (2)網絡攻擊 (3)計算環境:自身安全漏洞&#xf…

編輯器Sublime text 常用快捷命令 列模式 替換空行

平替notepad 下載可取官網 www.sublimetext.com 據說可以無限試用,沒有功能限制 1、快速刪除空行 ctrl h選擇正則表達式 .*Find輸入: ^(\t)*$\nReplace輸入:點擊Replace All 2、快速選擇指定字符 用鼠標選中alt f3修改 3、列編輯模式 ct…

如何理解HTML下的網頁結構?

HTML(Hypertext Markup Language)是一種標記語言,用于描述網頁的結構和內容。以下是對網頁結構的理解以及網絡爬蟲在處理不同類型網頁時可能遇到的情況: 1. HTML基本結構 HTML文檔的基本結構通常包括以下幾個部分: …

宇視科技視頻監控 main-cgi 文件信息泄露漏洞復現

0x01 產品簡介 宇視(Uniview)高清網絡攝像機是一種高性能的網絡攝像機,它可以通過網絡進行視頻傳輸和監控。該攝像機采用先進的視頻技術,具有高清晰度、低照度、寬動態等特點,能夠提供高質量的視頻圖像。 0x02 漏洞概述 宇視(Uniview)高清網絡攝像機存在信息泄露漏洞…

ppt編輯密碼如何設置?

大家在PPT中設置了限制編輯,發現后面任然可以編輯文件。那么如何將PPT文件設置成禁止修改模式呢?今天分享幾個方法給大家。 方法一 將PPT文件直接保存或者另存為一份文件,在保存時,將文件格式選擇為PowerPoint圖片演示文稿 方法…

.NET 8 編寫 LiteDB vs SQLite 數據庫 CRUD 接口性能測試(測試篇)

WebAppDbTest 項目測試 測試工具 ltt介紹安裝使用方式1、Drill2、Hammer3、Nailgun 測試主機規格配置CRUD 性能測試對比1、ltt 工具測試1.1、AddSingle 單條數據添加1.2、AddBulk 批量數據(1000)條添加1.3、GetSingle 單條數據查詢1.4、GetAll 多條&…

Spring Boot使用JUnit和Mockito進行Service層單元測試

文章目錄 前言一、單元測試是什么二、為什么要寫單元測試三、簡單示例假設我們有一個簡單的UserService類,其中包含了一些用戶相關的邏輯:首先,我們需要引入JUnit和Mockito的依賴。在Maven項目中,可以在pom.xml文件中添加以下依賴…

多合一iPhone 解鎖工具:iMyFone LockWiper iOS

多合一iPhone 解鎖工具 無需密碼解鎖 iPhone/iPad/iPod touch 上所有類型的屏幕鎖定 在幾分鐘內解鎖 iPhone Apple ID、Touch ID 和 Face ID 立即繞過 MDM 并刪除 iPhone/iPad/iPod touch 上的 MDM 配置文件 支持所有 iOS 版本和設備,包括最新的 iOS 17 和 iPhone 1…

SQL語句---查詢數據

介紹 使用sql語句查詢數據。 命令 select 字段1,字段2 from 表名;例子 查詢指定字段: select id,name from a;使用*查詢所有字段: select * from a;

JAVA實操經驗

零: 按照需要,可以使用需要某個類下(主要是java提供的)的方法來實現某個功能。(主要是用在不同類下的方法會進行重寫功能不同) 方法和構造方法不同:方法是方法,構造方法是構造器&a…

Kotlin 中的 `use` 關鍵字:優化資源管理(避免忘記inputStream.close() ?)

在 Android開發中,正確且高效地管理資源是至關重要的。use 關鍵字在 Kotlin 中為資源管理提供了一個簡潔且強大的解決方案。它主要用于自動管理那些需要關閉的資源,比如文件、網絡連接等。 一、use 關鍵字的工作原理 🤖 use 是一個擴展函數…

基于FPGA的視頻接口之高速IO

簡介 相對于其他視頻接口來說,高速IO接口(以Xilinx公司為例,spartan 6系列的GTP、Artix7系列的GTP,KENTEX7系列的GTX和GTH等)具有簡化設計、充分利用FPGA資源、降低設計成本等功能。 高速IO接口傳輸視頻,一般會被拓展為萬兆以太網、40G以太網、10G光纖、40G光纖、3G-SDI、…