日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

hive窗口函数最全总结

發(fā)布時(shí)間:2023/12/14 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hive窗口函数最全总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

準(zhǔn)備工作

一:窗口函數(shù)概況

1.1 窗口函數(shù)說(shuō)明

1.2 窗口范圍說(shuō)明

1.2.1 窗口范圍取值可選項(xiàng)

1.2.2 默認(rèn)窗口范圍含義

思考一:如何理解省略order by的情況,不能指定窗口范圍?

二:窗口函數(shù)分類(lèi)和特性

2.1 窗口函數(shù)分類(lèi)

2.2 窗口函數(shù)功能和常見(jiàn)應(yīng)用概括

2.2.1 功能

2.2.2 應(yīng)用

三:窗口函數(shù)應(yīng)用場(chǎng)景(基礎(chǔ)使用)

3.1 聚合型窗口函數(shù)

3.1.1 情境一:購(gòu)買(mǎi)物品的用戶(hù)及其總?cè)藬?shù)

3.1.2 情景二:用戶(hù)購(gòu)買(mǎi)物品明細(xì)及每周各種類(lèi)型用戶(hù)購(gòu)買(mǎi)總數(shù)量(補(bǔ)分析列)。

3.2 分析型(排序)窗口函數(shù)

3.2.1情景三:每種用戶(hù)類(lèi)型銷(xiāo)量排行第一的用戶(hù)及其明細(xì)(分組排名)

思考二:窗口排序遇到null

3.2.2 情景四:每種用戶(hù)類(lèi)型銷(xiāo)量排名前2的用戶(hù)明細(xì)(top n)

3.1.4 情景五:連續(xù)n天登陸

情景六:給定數(shù)字的頻率查詢(xún)中位數(shù)

3.3 取值型窗口函數(shù)

3.3.1 準(zhǔn)備工作

3.3.2 情景七:找到車(chē)輛上一次鎖車(chē)記錄

3.3.3 情景八:那么如何求某個(gè)省份圍欄、某小時(shí)、某輛車(chē)的最長(zhǎng)未被騎行時(shí)間。(多次窗口使用)

思考三:多次窗口使用能否改成一次窗口和group by結(jié)合得到大致數(shù)據(jù)?

思考四:多次窗口使用能否改成一次窗口和group by結(jié)合得到所有明細(xì)數(shù)據(jù)?

3.3.4 情景九:連續(xù)出現(xiàn)的數(shù)字

四:進(jìn)階使用

4.1 窗口函數(shù)與group by異同點(diǎn)

4.1.1 窗口函數(shù)與group by 區(qū)別

4.1.2 group by去重

4.2 collect_list + partition by的特殊用法

4.2.1 問(wèn)題提出

4.2.2 解決思路

4.2.3 實(shí)際解決

4.2.4 延伸到風(fēng)控業(yè)務(wù)的實(shí)際用法

4.3 cube&grouping set這塊

五:窗口函數(shù)底層運(yùn)行原理

六:其他注意事項(xiàng)

思考問(wèn)題:

思考一:如何理解省略order by的情況,不能指定窗口范圍?

思考二:窗口排序遇到null

準(zhǔn)備工作

已經(jīng)有測(cè)試表:order_detail.本文接下來(lái)所有測(cè)試樣例如果未特殊說(shuō)明均基于下面order_detail表。

user_id

(用戶(hù)ID)

order_date

(訂單日期)

user_type

(用戶(hù)類(lèi)型)

sales

(銷(xiāo)量)

1

qishili

2022-07-03

new

5

2

wangshi

2022-07-01

old

2

3

liiu

2022-07-01

new

1

4

lilisi

2022-07-05

new

5

5

lisi

2022-07-02

old

1

6

wutong

2022-07-02

new

6

7

qibaqiu

2022-07-05

new

1

8

liwei

2022-07-02

old

3

9

zhangsa

2022-07-02

new

2

10

wanger

2022-07-02

new

3

一:窗口函數(shù)概況

1.1 窗口函數(shù)說(shuō)明

窗口函數(shù)簡(jiǎn)單的說(shuō)就是在執(zhí)行聚合函數(shù)的時(shí)候指定一個(gè)操作窗口,這個(gè)窗口由over來(lái)進(jìn)行控制。接下來(lái)重點(diǎn)介紹一下over()函數(shù)。

over():指定分析函數(shù)工作的數(shù)據(jù)窗口大小,這個(gè)大小可能會(huì)隨著行的變化而變化。

其基本語(yǔ)法如下:<分析函數(shù)> over ( partition by <用于分組的列名> order by <用于排序的列名> desc/asc rows between 開(kāi)始行 and 結(jié)束行 )

樣例1--窗口函數(shù)基本使用

select user_id,user_type,sales,count(user_id) over(partition by user_type order by sales desc rows between unbounded preceding and current row) as cnt from order_detail

可以看到over()里面一共有3部分組成:分區(qū)、排序、指定窗口范圍,注意這三部分可以組合使用,也可以不使用。

  • partition by可以理解為分組。over(partition by 列)搭配分析函數(shù)時(shí)候(可以接多個(gè)列,表示按照這些列分組),分析函數(shù)是按照每一組的數(shù)據(jù)進(jìn)行分析計(jì)算的。

  • order by是在窗口內(nèi)進(jìn)行排序,desc/asc可以進(jìn)行選擇使用。

  • rows between 開(kāi)始位置 and 結(jié)束位置,指定數(shù)據(jù)范圍。 -- 例如常使用的窗口范圍是rows between unbounded preceding and current row.常用該窗口來(lái)累加計(jì)算。

  • 1.2 窗口范圍說(shuō)明

    1.2.1 窗口范圍取值可選項(xiàng)

    1)范圍取值

    【a:rows+參數(shù)來(lái)控制范圍】

    • 默認(rèn)值(不寫(xiě)):這個(gè)其實(shí)是最常用的,下面會(huì)進(jìn)行不同情況下默認(rèn)值總結(jié)

    • preceding:往前;

    • following: 往后

    • current row:當(dāng)前行

    • unbounded :起點(diǎn)(一般結(jié)合preceding,following使用)

    • unbounded preceding: 表示該窗口最前面的行(起點(diǎn))

    • unbounded following:該窗口最后面的行(終點(diǎn))

    樣例2--窗口范圍一些完整寫(xiě)法

    rows between unbounded preceding and current row --(表示從窗口起點(diǎn)到當(dāng)前行) rows?between unbounded preceding and unbounded following--(表示從窗口起點(diǎn)到終點(diǎn)) rows between 2 preceding and 1 following --(表示往前2行到往后1行) rows between 2 preceding and 1 current row --(表示往前兩行到當(dāng)前行) rows between current row and unbounded following --(表示當(dāng)前行到終點(diǎn)) 【b.range between來(lái)控制范圍】

    range 表示的是值, 表示比這個(gè)值小n的行,比這個(gè)值大n的行即range between 是以當(dāng)前值為錨點(diǎn)進(jìn)行計(jì)算。

    eg: sum(sales) range between 100 preceding and 200 following

    【c.通過(guò)窗口函數(shù)來(lái)控制范圍】

    • lag(col, n, default_val): 往前第n行數(shù)據(jù),沒(méi)有數(shù)據(jù)的話(huà)用default_value代替

    • lead(col, n, default_val):往后第n行數(shù)據(jù),沒(méi)有數(shù)據(jù)的話(huà)用default_value代替

    • ntile(n):把有序分區(qū)中的行分發(fā)到指定數(shù)據(jù)的組中,各個(gè)組有編號(hào),編號(hào)從1開(kāi)始,對(duì)于每一行,NTILE返回此行所屬的組的編號(hào)。注意:n必須為int類(lèi)型.

    2)為了解釋rows between unbounded preceding and current rowrows?between unbounded preceding and unbounded following,我們舉例說(shuō)明:

    樣例3--rows between and取值范圍區(qū)別

    select user_id,user_type,sales,count(user_id) over(partition by user_type order by sales desc rows between unbounded preceding and current row) as current_cnt, -- 樣例1中的代碼: 窗口取到當(dāng)前行count(user_id) over(partition by user_type order by sales desc rows between unbounded preceding and unbounded following) as unbounded_following_cnt -- 窗口取到所有行 from order_detail

    樣例3測(cè)試結(jié)果(如下表),可以看出:

    • 當(dāng)指定范圍是從頭到當(dāng)前行,分析函數(shù)得到的這個(gè)局部范圍(動(dòng)態(tài)變化的)的分析值,例如current_cnt,每一行記錄得到的都是一個(gè)變化的值(同一個(gè)分組內(nèi)不同行值都是不同的)。(再具體一點(diǎn)是到每個(gè)組中的某一行記錄)

    • 當(dāng)指定范圍是開(kāi)頭到末尾行,分析函數(shù)得到的是全局范圍(固定的)的分析值,例如unbounded_following_cnt,同一個(gè)組每一行記錄都是一個(gè)相等值(指同一個(gè)分組內(nèi)哈,不同分組值還是不同的)。

    user_id

    order_date

    user_type

    sales

    current_cnt

    unbounded_following_cnt

    1

    wutong

    2022-07-01

    new

    6

    1

    7

    2

    lilisi

    2022-07-02

    new

    5

    3

    7

    3

    qishili

    2022-07-02

    new

    5

    3

    7

    4

    wanger

    2022-07-01

    new

    3

    4

    7

    5

    zhangsa

    2022-07-03

    new

    2

    5

    7

    6

    qibaqiu

    2022-07-06

    new

    1

    7

    7

    7

    liiu

    2022-07-05

    new

    1

    7

    7

    8

    liwei

    2022-07-05

    old

    3

    1

    3

    9

    wangshi

    2022-07-02

    old

    2

    2

    3

    10

    lisi

    2022-07-01

    old

    1

    3

    3

    1.2.2 默認(rèn)窗口范圍含義

    1)情況一:當(dāng)over()里面有partition by和order by的時(shí)候,但是缺少rows between and這部分,即不寫(xiě)這塊,也就是我們常說(shuō)的默認(rèn)值,其分析函數(shù)對(duì)應(yīng)的范圍是同一組從開(kāi)頭到當(dāng)前值。

    上面的默認(rèn)窗口范圍和樣例2中的窗口范圍區(qū)別:

    樣例4--既有partition by和order by情況下默認(rèn)值窗口范圍和常見(jiàn)窗口范圍比較

    select user_id,user_type,sales,sum(sales) over(partition by user_type order by sales desc rows between unbounded preceding and current row) as current_cnt, -- 樣例1中的代碼: 窗口取到各組當(dāng)前行(當(dāng)前這行的記錄)sum(sales) over(partition by user_type order by sales desc) as default_cnt, -- 默認(rèn)也是窗口取到各組當(dāng)前行,但是更準(zhǔn)確的說(shuō)應(yīng)該是取到各組當(dāng)前值,因?yàn)閛rder by之后,-- 當(dāng)排序的字段相同的時(shí)候,-- 相同的字段會(huì)一起被計(jì)算出來(lái),所以說(shuō)是取到當(dāng)前“值/行”。會(huì)把值相同的進(jìn)行一起計(jì)算,-- 得到某一個(gè)結(jié)果。sum(sales) over(partition by user_type order by sales desc rows between unbounded preceding and unbounded following) as unbounded_following_cnt-- 窗口取到所有行 ,各個(gè)分組里面也取所有行,各個(gè)組里面只有同一個(gè)值 from order_detail

    樣例4測(cè)試結(jié)果(如下表),可以清楚看到:

    • rows between unbounded preceding and current row其分析計(jì)算出來(lái)的結(jié)果是針對(duì)開(kāi)頭到當(dāng)前行的范圍,所以同一組的各個(gè)記錄對(duì)應(yīng)的分析值也不一樣;

    • 而默認(rèn)不寫(xiě)窗口范圍的,其分析是針對(duì)開(kāi)頭到當(dāng)前值的范圍,因?yàn)楫?dāng)前值可以對(duì)應(yīng)多條記錄,需要把這幾天記錄一起去分析得到一個(gè)明確的結(jié)果,然后這個(gè)值所對(duì)應(yīng)的這幾條記錄最終都是這同一個(gè)明確的結(jié)果。

    • 而窗口范圍明確寫(xiě)開(kāi)頭到結(jié)尾,那么同一個(gè)組內(nèi)所有記錄都是同一個(gè)結(jié)果,分析的是同一個(gè)組的所有數(shù)據(jù)。

    user_id

    user_type

    sales

    current_cnt

    default_cnt

    unbounded_following_cnt

    1

    wutong

    new

    6

    1

    1

    7

    2

    lilisi

    new

    5

    2

    3

    7

    3

    qishili

    new

    5

    3

    3

    7

    4

    wanger

    new

    3

    4

    4

    7

    5

    zhangsa

    new

    2

    5

    5

    7

    6

    liiu

    new

    1

    6

    7

    7

    7

    qibaqiu

    new

    1

    7

    7

    7

    8

    liwei

    old

    3

    1

    1

    3

    9

    wangshi

    old

    2

    2

    2

    3

    10

    lisi

    old

    1

    3

    3

    3

    2)情況二:當(dāng)over里面只有partiton by,沒(méi)有order by的時(shí)候,注意這個(gè)時(shí)候?qū)懙拇翱诜秶荒軐?xiě)樣例2的范圍,會(huì)直接報(bào)錯(cuò),只能按照默認(rèn)范圍來(lái)。默認(rèn)范圍是從分組內(nèi)開(kāi)頭到結(jié)尾的記錄即ows between unbounded preceding and unbounded following,雖然范圍是這個(gè),但是sql代碼不能寫(xiě)上ows between unbounded preceding and unbounded following,只能什么也不寫(xiě)。(因?yàn)闆](méi)有order by每次數(shù)據(jù)記錄返回來(lái)的順序可能不一致)。

    樣例5--窗口里面只有partition by

    -- 只partition by select user_id,user_type,sales,sum(sales) over(partition by user_type ) as default_cnt -- 默認(rèn)-- sum(sales) over(partition by user_type rows between unbounded -- preceding and unbounded following) as unbounded_following_cnt -- 直接報(bào)錯(cuò),不能寫(xiě)出窗口范圍。 from order_detail

    樣例5測(cè)試結(jié)果:可以看待窗口范圍是各個(gè)分組里面開(kāi)頭到結(jié)尾的數(shù)據(jù),各個(gè)組分析得到的結(jié)果一樣。

    1

    zhangsa

    new

    2

    23

    2

    wanger

    new

    3

    23

    3

    liiu

    new

    1

    23

    4

    qibaqiu

    new

    1

    23

    5

    wutong

    new

    6

    23

    6

    lilisi

    new

    5

    23

    7

    qishili

    new

    5

    23

    8

    lisi

    old

    1

    6

    9

    wangshi

    old

    2

    6

    10

    liwei

    old

    3

    6

    3)情況三:當(dāng)over()里面只有order by的時(shí)候,這個(gè)時(shí)候窗口范圍的控制就和情況一中一樣,可以,只不過(guò)這個(gè)時(shí)候就只有一個(gè)分組了,全部數(shù)據(jù)放到一個(gè)分組里面

    常用的窗口范圍和默認(rèn)窗口范圍見(jiàn)情況一,這里不再贅述。

    樣例6--窗口里面沒(méi)有partition by,有order by

    select user_id,user_type,sales,sum(sales) over(order by sales desc rows between unbounded preceding and current row) as current_cnt, -- 樣例1中的代碼: 窗口取到當(dāng)前行sum(sales) over(order by sales desc) as default_cnt, -- 默認(rèn):取到當(dāng)前“行/值”sum(sales) over(order by sales desc rows between unbounded preceding and unbounded following) as unbounded_following_cnt -- 窗口取到所有行 from order_detail

    樣例6測(cè)試結(jié)果

    user_id

    user_type

    sales

    current_cnt

    default_cnt

    unbounded_following_cnt

    1

    wutong

    new

    6

    6

    6

    29

    2

    lilisi

    new

    5

    11

    16

    29

    3

    qishili

    new

    5

    16

    16

    29

    4

    wanger

    new

    3

    19

    22

    29

    5

    liwei

    old

    3

    22

    22

    29

    6

    zhangsa

    new

    2

    24

    26

    29

    7

    wangshi

    old

    2

    26

    26

    29

    8

    lisi

    old

    1

    27

    29

    29

    9

    liiu

    new

    1

    28

    29

    29

    10

    qibaqiu

    new

    1

    29

    29

    29

    4)情況四:當(dāng)窗口里面既沒(méi)有partition by,也沒(méi)有order by的時(shí)候

    樣例7--既沒(méi)有partition by也沒(méi)有order by的時(shí)候

    select user_id,user_type,sales,-- sum(sales) over(rows between unbounded preceding and current row) -- as current_cnt, -- 錯(cuò)誤寫(xiě)法 ,也就是說(shuō)這種情況下,我們也不能自己寫(xiě)窗口范圍。sum(sales) over() as sales_cnt -- 默認(rèn) 正確寫(xiě)法 范圍默認(rèn)為開(kāi)頭到結(jié)尾。-- sum(sales) over(rows between unbounded preceding and --unbounded following) as unbounded_following_cnt -- 錯(cuò)誤寫(xiě)法 from order_detail

    5)對(duì)上面5種情況進(jìn)行初步總結(jié):

    • 如果over()里面沒(méi)有order by,那么我們就不能指定窗口范圍,只能使用默認(rèn)值(代碼中row between end這處什么也不寫(xiě)),此時(shí)的默認(rèn)值代表的范圍是各分組的開(kāi)頭到結(jié)尾數(shù)據(jù);

    • 反之,如果over()里面🈶?order by,那么我們就可以指定窗口范圍,如果不指定窗口范圍(默認(rèn)值),此時(shí)默認(rèn)值的范圍代表分組里面的的開(kāi)頭到當(dāng)前值(當(dāng)前“行”)的數(shù)據(jù)范圍。

    • 如果over里面沒(méi)有partition by,此時(shí)就只有一個(gè)分組,同上一樣。

    思考一:如何理解省略order by的情況,不能指定窗口范圍?

    在任何并行系統(tǒng)中,如果order by子句未生成唯一排序和總排序,則行的順序是不確定的,也就是說(shuō),如果order by 表達(dá)式生成重復(fù)的值(部分排序),則這些行的返回順序可能會(huì)有差別,也就是說(shuō)窗口函數(shù)可能返回意外或不一致的結(jié)果。

    二:窗口函數(shù)分類(lèi)和特性

    2.1 窗口函數(shù)分類(lèi)

    1)按照窗口來(lái)分

    可以分為靜態(tài)窗口函數(shù)、動(dòng)態(tài)窗口函數(shù)。其中靜態(tài)窗口函數(shù)主要是指排序函數(shù);而動(dòng)態(tài)窗口函數(shù)主要分為累計(jì)計(jì)算函數(shù)和偏分析函數(shù)。其中窗口數(shù)據(jù)集這塊對(duì)應(yīng)文章第一章的詳細(xì)描述。

    窗口函數(shù)窗口函數(shù)名窗口數(shù)據(jù)集靜態(tài)窗口函數(shù)動(dòng)態(tài)窗口函數(shù)

    排序函數(shù)row_number():當(dāng)前行在組內(nèi)的排序,eg:1,2,3,4,5

    dense_rank()不間斷組內(nèi)排序,eg:1,1,2,3,3

    rank():間斷的組內(nèi)排序,eg:1,1,3,4,5

    累計(jì)計(jì)算函數(shù)偏移分析函數(shù)sum()count()avg()max()min()percent_rank():累計(jì)百分比cume_dist():累計(jì)分布值first_value():返回組內(nèi)第一個(gè)值last_value():返回組內(nèi)的最后一個(gè)值nth_value():返回組內(nèi)的第n行l(wèi)ag():從當(dāng)前行往上偏移第n行,默認(rèn)為nulllead():從當(dāng)前行開(kāi)始向下偏移第n行,默認(rèn)為nullntile():返回當(dāng)前行在組內(nèi)截止當(dāng)前行的第n行分組參數(shù):partition by排序參數(shù):order by窗口參數(shù):row between ...andover()

    2)按照函數(shù)功能

    可以將窗口函數(shù)分為:聚合型窗口函數(shù)、分析型窗口函數(shù)、取值型窗口函數(shù)。

    窗口函數(shù)聚合型取值型分析型聚合函數(shù):sum() /max() /min() /avg() /count()排序函數(shù)和占比函數(shù):row_number() / dense_rank() / rank() / percent_rank() /cume_dist()?取值:lag() / lead() / first_value() / last_value()

    3)舉例擴(kuò)展一下窗口函數(shù)中三個(gè)排序函數(shù)區(qū)別

    樣例8--三個(gè)排序函數(shù)區(qū)別(每種用戶(hù)類(lèi)型銷(xiāo)量排名)

    select user_id,user_type,sales,row_number() over(partition by user_type order by sales) as rn,dense_rank() over(partition by user_type order by sales) as rd,rank() over(partition by user_type order by sales) as rr from order_detail

    樣例8測(cè)試結(jié)果:

    user_id

    user_type

    sales

    rn

    rd

    rr

    1

    liiu

    new

    1

    1

    1

    1

    2

    qibaqiu

    new

    1

    2

    1

    1

    3

    zhangsa

    new

    2

    3

    2

    3

    4

    wanger

    new

    3

    4

    3

    4

    5

    lilisi

    new

    5

    5

    4

    5

    6

    qishili

    new

    5

    6

    4

    5

    7

    wutong

    new

    6

    7

    5

    7

    8

    lisi

    old

    1

    1

    1

    1

    9

    wangshi

    old

    2

    2

    2

    2

    10

    liwei

    old

    3

    3

    3

    3

    2.2 窗口函數(shù)功能和常見(jiàn)應(yīng)用概括

    2.2.1 功能

    1)窗口函數(shù)同時(shí)具有分組和排序的功能;

    2)不減少原有表的行數(shù)。即窗口函數(shù)可以理解為在本行內(nèi)做運(yùn)算,每一行對(duì)應(yīng)一行的值。

    3)可指定窗口數(shù)據(jù)范圍

    2.2.2 應(yīng)用

    1)分組排名問(wèn)題

    2)top n問(wèn)題

    3)連續(xù)登陸問(wèn)題

    4)加一分析結(jié)果列

    5)累計(jì)問(wèn)題

    6)上一個(gè)下一個(gè)記錄問(wèn)題

    三:窗口函數(shù)應(yīng)用場(chǎng)景(基礎(chǔ)使用)

    3.1 聚合型窗口函數(shù)

    sum,count()這些很常見(jiàn),其功能我們不再贅述

    3.1.1 情境一:購(gòu)買(mǎi)物品的用戶(hù)及其總?cè)藬?shù)

    樣例9--查詢(xún)2022年7月份購(gòu)買(mǎi)物品的用戶(hù)及其總?cè)藬?shù)

    -- 正確方法:總?cè)藬?shù)是指7月份購(gòu)買(mǎi)物品的總?cè)藬?shù)。 select user_id,count(1) over() as 7_mounth_all_cnt from order_detail where substring(order_date,1,7) = '2022-07' -- 錯(cuò)誤理解;不是每個(gè)人購(gòu)買(mǎi)物品總?cè)藬?shù)。 select user_id,count(1) as 7_mounth_all_cnt from order_detail where substring(order_date,1,7) = '2022-07' group by user_id

    樣例9測(cè)試結(jié)果:

    user_id

    7_mounth_all_cnt

    1

    qibaqiu

    10

    2

    zhangsa

    10

    3

    lisi

    10

    4

    wanger

    10

    5

    liiu

    10

    6

    wangshi

    10

    7

    liwei

    10

    8

    wutong

    10

    9

    lilisi

    10

    10

    qishili

    10

    3.1.2 情景二:用戶(hù)購(gòu)買(mǎi)物品明細(xì)及每周各種類(lèi)型用戶(hù)購(gòu)買(mǎi)總數(shù)量(補(bǔ)分析列)。

    樣例10:用戶(hù)購(gòu)買(mǎi)物品明細(xì)以及每周各種類(lèi)型用戶(hù)購(gòu)買(mǎi)總數(shù)量

    select user_id,user_type,sales,sum(sales) over(partition by week(order_date),user_type) as sales_s from order_detail

    樣例10測(cè)試結(jié)果如下,像這樣既要明細(xì)又需要聚合值的,顯然使用group by是做不到的,要使用窗口函數(shù)。

    user_id

    user_type

    sales

    sales_s

    wanger

    new

    3

    20

    2

    qibaqiu

    new

    1

    20

    3

    wutong

    new

    6

    20

    4

    lilisi

    new

    5

    20

    5

    qishili

    new

    5

    20

    6

    lisi

    old

    1

    3

    7

    wangshi

    old

    2

    3

    8

    zhangsa

    new

    2

    3

    9

    liiu

    new

    1

    3

    10

    liwei

    old

    3

    3

    3.2 分析型(排序)窗口函數(shù)

    在第二章中已經(jīng)對(duì)常見(jiàn)排序函數(shù)進(jìn)行總結(jié)過(guò),可參考。

    3.2.1情景三:每種用戶(hù)類(lèi)型銷(xiāo)量排行第一的用戶(hù)及其明細(xì)(分組排名

    可以參照第二章中的樣例7。

    樣例11:每種用戶(hù)類(lèi)型銷(xiāo)量排行第一的用戶(hù)及其明細(xì)(分組排序)

    -- 把窗口函數(shù)放在自查詢(xún)里面得到一個(gè)每條記錄的排名 select * from (select user_id,user_type,sales,row_number() over(partition by user_type order by sales desc) as rcfrom order_detail )t1 where t1.rc = 1

    樣例11測(cè)試結(jié)果:

    user_id

    user_type

    sales

    rc

    1

    wutong

    new

    6

    1

    2

    liwei

    old

    3

    1

    思考二:窗口排序遇到null

    1)窗口中order by的 時(shí)候,使用desc降序排列的時(shí)候,null值排在首位

    使用asc升序的時(shí)候,null值排在末尾

    2)如何控制null的位置:

    nulls last和 nulls first.

    如下圖:此樣例建議等看完第四章中部分論述的背景,再回來(lái)看這個(gè)

    rrow_number() over(partition by fence,hour(lock_time),bike_id order by time_gap desc nulls last) as rc

    樣例12:排序的時(shí)候不需要先對(duì)null值進(jìn)行處理,直接使用nulls last會(huì)很省事!

    select -- 找到分組中最大間隔fence,hourtime,bike_id,time_gap from ( -- 分組對(duì)時(shí)間間隔進(jìn)行排序selectfence,bike_id,hour(lock_time) as hourtime,time_gap,-- 發(fā)現(xiàn)time_gap存在很多null的情況,在參與order by排序的時(shí)候會(huì)影響排序結(jié)果,所以得到結(jié)果不準(zhǔn)確row_number() over(partition by fence,hour(lock_time),bike_id order by time_gap desc nulls last) as rcfrom( -- 分組找到本次記錄的上次記錄的鎖車(chē)時(shí)間和事件間隔select fence,bike_id,hour(lock_time),unlock_time,lock_time,lag(unlock_time,1,null) over(partition by fence,hour(lock_time),bike_id) as last_unlock_time,(unix_timestamp(unlock_time) - unix_timestamp(lag(lock_time,1,null) over(partition by fence,hour(lock_time),bike_id))) as time_gapfrom bike_hour_inc)t1 )t2 where t2.rc =1 order by fence,hourtime,bike_id ?

    3.2.2 情景四:每種用戶(hù)類(lèi)型銷(xiāo)量排名前2的用戶(hù)明細(xì)(top n

    可以參照第二章中的樣例7

    樣例13:每種用戶(hù)類(lèi)型銷(xiāo)量排名前2的用戶(hù)明細(xì)

    -- 自查詢(xún)使用窗口函數(shù)得到分組里面每條記錄排名,外查詢(xún)進(jìn)行排名的約束 select * from (select user_id,user_type,sales,row_number() over(partition by user_type order by sales desc) as rcfrom order_detail )t1 where t1.rc <=2

    樣例13測(cè)試結(jié)果:

    user_id

    user_type

    sales

    rc

    1

    wutong

    new

    6

    1

    2

    lilisi

    new

    5

    2

    3

    liwei

    old

    3

    1

    4

    wangshi

    old

    2

    2

    3.1.4 情景五:連續(xù)n天登陸

    給定測(cè)試數(shù)據(jù)集


    7

    2022-06-02

    7

    2022-06-10

    7

    2022-06-03

    7

    2022-05-30

    7

    2022-05-31

    7

    2022-06-02

    1

    2022-06-07

    7

    2022-06-01

    1

    2022-05-30

    sql邏輯

    樣例14:連續(xù)n天登陸(去重、排序、間隔、分組、約束)

    select login_id from ( selectlogin_id,login_date,-- row_number() over(partition by login_id order by login_date) as rc -- 對(duì)登陸日期進(jìn)行排名-- 找到登陸日期與時(shí)間排名之間的間隔date_sub(login_date,row_number() over(partition by login_id order by login_date) ) as time_gap from (-- 每個(gè)人一天可能不止登陸一次,需要去重select login_id,login_datefrom login_tablegroup by login_id,login_date)t1)t2group by t2.login_id,t2.time_gap -- 以用戶(hù)和時(shí)間間隔進(jìn)行分組having count(1) >= 5 -- 每個(gè)用戶(hù)分組和時(shí)間間隔分組里面數(shù)據(jù)記錄大于等于5的。

    測(cè)試結(jié)果login_id = 7;

    情景六:給定數(shù)字的頻率查詢(xún)中位數(shù)

    todo

    3.3 取值型窗口函數(shù)

    3.3.1 準(zhǔn)備工作

    1)lag/lead() over()的使用

    lag(col,n,default):用于統(tǒng)計(jì)窗口往上第n行值:

    • 第一個(gè)參數(shù)為列名;

    • 第二個(gè)參數(shù)為往上第n行(默認(rèn)為1);

    • 第三個(gè)參數(shù)為默認(rèn)值(當(dāng)往上第n行為null的時(shí)候,取默認(rèn)值,如果不指定,則取null)。

    同理:

    lead(col,n,default):用于統(tǒng)計(jì)窗口往下第n行值:

    • 第一個(gè)參數(shù)為列名;

    • 第二個(gè)參數(shù)為往下第n行(默認(rèn)為1);

    • 第三個(gè)參數(shù)為默認(rèn)值(當(dāng)往下第n行為null的時(shí)候,取默認(rèn)值,如果不指定,則取null)。

    • 窗口partition by和group by

    • 是否添加范圍

    2)first_value

    todo

    思考:first_value與max()區(qū)別???

    3.3.2 情景七:找到車(chē)輛上一次鎖車(chē)記錄

    類(lèi)似情景表述:查看顧客上次的購(gòu)買(mǎi)時(shí)間

    某車(chē)輛在某一小時(shí)內(nèi)某一圍欄中本次騎行的明細(xì)及對(duì)應(yīng)上次鎖車(chē)時(shí)間。新的測(cè)試數(shù)據(jù)集:

    fence

    bike_id

    unlock_time

    lock_time

    1

    湖北

    101

    2022-09-01 07:03:23

    2022-09-01 07:05:03

    2

    湖北

    101

    2022-09-01 07:12:53

    2022-09-01 07:15:13

    3

    湖北

    101

    2022-09-01 07:32:11

    2022-09-01 07:55:13

    4

    湖北

    101

    2022-09-01 07:56:11

    2022-09-01 07:59:52

    5

    湖北

    101

    2022-09-01 09:12:10

    2022-09-01 09:25:53

    6

    湖北

    101

    2022-09-01 09:42:09

    2022-09-01 09:45:33

    7

    湖北

    102

    2022-09-01 07:02:21

    2022-09-01 07:15:13

    8

    湖北

    102

    2022-09-01 07:47:21

    2022-09-01 07:55:13

    9

    山東

    104

    2022-09-01 07:02:21

    2022-09-01 07:15:13

    10

    山東

    104

    2022-09-01 07:44:21

    2022-09-01 07:55:13

    樣例15:某哈羅單車(chē)車(chē)輛在某一小時(shí)內(nèi)某一圍欄中本次騎行的明細(xì)及對(duì)應(yīng)上次鎖車(chē)時(shí)間?,沒(méi)有order by

    select fence,bike_id,unlock_time, -- 開(kāi)鎖lock_time, -- 鎖車(chē)lag(lock_time,1,null) over(partition by fence,hour(unlock_time),bike_id) as last_lock_time from bike_hour_inc

    測(cè)試結(jié)果

    fence

    bike_id

    unlock_time

    lock_time

    last_lock_time

    (本次開(kāi)鎖時(shí)間對(duì)應(yīng)的上一次鎖車(chē)時(shí)間)

    1

    山東

    104

    2022-09-01 07:02:21

    2022-09-01 07:15:13

    null

    2

    山東

    104

    2022-09-01 07:44:21

    2022-09-01 07:55:13

    2022-09-01 07:15:13

    3

    湖北

    101

    2022-09-01 07:03:23

    2022-09-01 07:05:03

    null

    4

    湖北

    101

    2022-09-01 07:12:53

    2022-09-01 07:15:13

    2022-09-01 07:05:03

    5

    湖北

    101

    2022-09-01 07:32:11

    2022-09-01 07:55:13

    2022-09-01 07:15:13

    6

    湖北

    101

    2022-09-01 07:56:11

    2022-09-01 07:59:52

    2022-09-01 07:55:13

    7

    湖北

    102

    2022-09-01 07:02:21

    2022-09-01 07:15:13

    null

    8

    湖北

    102

    2022-09-01 07:47:21

    2022-09-01 07:55:13

    2022-09-01 07:15:13

    9

    湖北

    101

    2022-09-01 09:12:10

    2022-09-01 09:25:53

    null

    10

    湖北

    101

    2022-09-01 09:42:09

    2022-09-01 09:45:33

    2022-09-01 09:25:53

    111

    3.3.3 情景八:那么如何求某個(gè)省份、某小時(shí)、某拖拉機(jī)的最長(zhǎng)未被騎行時(shí)間。(多次窗口使用)

    樣例16:各車(chē)輛在某一省份分小時(shí)段最大未騎行間隔(不完全對(duì)的寫(xiě)法,忽視了null排序情況)

    -- 注意:最里層自查詢(xún)要在窗口里面使用partition by進(jìn)行分組,在外層查詢(xún)里面對(duì)時(shí)間間隔排序也需要分組 select -- 找到分組中最大間隔fence,hourtime,bike_id,time_gap from ( -- 分組對(duì)時(shí)間間隔進(jìn)行排序selectfence,bike_id,hour(lock_time) as hourtime,time_gap,-- 發(fā)現(xiàn)time_gap存在很多null的情況,在參與order by排序的時(shí)候會(huì)影響排序結(jié)果,所以得到結(jié)果不準(zhǔn)確row_number() over(partition by fence,hour(lock_time),bike_id order by time_gap desc) as rcfrom( -- 分組找到本次記錄的上次記錄的鎖車(chē)時(shí)間和事件間隔select fence,bike_id,hour(lock_time),unlock_time,lock_time,lag(unlock_time,1,null) over(partition by fence,hour(lock_time),bike_id) as last_unlock_time,(unix_timestamp(unlock_time) - unix_timestamp(lag(lock_time,1,null) over(partition by fence,hour(lock_time),bike_id order by unlock_time))) as time_gapfrom bike_hour_inc)t1 )t2 where t2.rc =1 order by fence,hourtime,bike_id

    測(cè)試結(jié)果:

    fence

    hourtime

    bike_id

    time_gap

    1

    山東

    7

    104

    1748

    2

    湖北

    7

    101

    58

    3

    湖北

    7

    102

    1928

    4

    湖北

    9

    101

    976

    糾正后,最終正確寫(xiě)法1:對(duì)null先進(jìn)行處理

    樣例17:各拖拉機(jī)在某一省份分小時(shí)段最大未騎行間隔(兩次窗口函數(shù)完全正確寫(xiě)法)

    select * from (select t2.fence,t2.bike_id,t2.every_hour,t2.unlock_time,t2.lock_time,t2.last_lock_time,t2.time_gap,t2.time_gap_not_null,row_number() over(partition by t2.fence,t2.every_hour,t2.bike_id order by time_gap_not_null desc) as rcfrom(select t1.fence,t1.bike_id,t1.every_hour,t1.unlock_time,t1.lock_time,t1.last_lock_time,t1.time_gap,case when t1.time_gap is not null then t1.time_gap else -1 end as time_gap_not_null-- nvl(t1.time_gap,999999) as time_gap_not_null2 -- 不行,數(shù)值類(lèi)型不一樣的感覺(jué)。from(select fence,bike_id,hour(lock_time) as every_hour,unlock_time,lock_time,-- 使用lag,窗口里面應(yīng)該需要加一個(gè)order by吧!lag(lock_time,1,null) over(partition by fence,hour(unlock_time),bike_id order by unlock_time) as last_lock_time,(unix_timestamp(unlock_time) - unix_timestamp(lag(lock_time,1,null) over(partition by fence,hour(lock_time),bike_id order by unlock_time))) as time_gapfrom bike_hour_inc)t1)t2 )t3 where t3.rc =1 order by t3.fence,t3.every_hour,t3.bike_id

    測(cè)試結(jié)果:

    fence

    bike_id

    hour

    unlock_time

    lock_time

    last_lock_time

    time_gap

    time_gap_not_null

    rc

    1

    山東

    104

    7

    2022-09-01 07:44:21

    2022-09-01 07:55:13

    2022-09-01 07:15:13

    1748

    1748

    1

    2

    湖北

    101

    7

    2022-09-01 07:32:11

    2022-09-01 07:55:13

    2022-09-01 07:15:13

    1018

    1018

    1

    3

    湖北

    102

    7

    2022-09-01 07:47:21

    2022-09-01 07:55:13

    2022-09-01 07:15:13

    1928

    1928

    1

    4

    湖北

    101

    9

    2022-09-01 09:42:09

    2022-09-01 09:45:33

    2022-09-01 09:25:53

    976

    976

    1

    糾正后,正確寫(xiě)法(第二種辦法)

    見(jiàn)3.4節(jié)樣例12。

    注意事項(xiàng):

    1)null在窗口中排序問(wèn)題:(回去看3.4節(jié)的論述)

    2)nvl()字段類(lèi)型問(wèn)題

    3)多重子查詢(xún)

    4)兩次分組

    思考三:多次窗口使用能否改成一次窗口和group by結(jié)合得到大致數(shù)據(jù)?

    子查詢(xún)里面使用窗口,外查詢(xún)里面也使用窗口

    外查詢(xún)?nèi)绻皇褂么翱诤瘮?shù)partition by分組,我們也可以使用group by后取max即可。

    樣例18:各車(chē)輛在某一圍欄分小時(shí)段最大未騎行間隔(使用group by+一次窗口函數(shù)? )

    -- 原始版 select t2.fence,t2.bike_id,t2.every_hour,max(t2.time_gap_not_null) as max_gapfrom(select t1.fence,t1.bike_id,t1.every_hour,t1.unlock_time,t1.lock_time,t1.last_lock_time,t1.time_gap,case when t1.time_gap is not null then t1.time_gap else -1 end as time_gap_not_null-- nvl(t1.time_gap,999999) as time_gap_not_null2 -- 不行,數(shù)值類(lèi)型不一樣的感覺(jué)。from(select fence,bike_id,hour(lock_time) as every_hour,unlock_time,lock_time,lag(lock_time,1,null) over(partition by fence,hour(unlock_time),bike_id) as last_lock_time,(unix_timestamp(unlock_time) - unix_timestamp(lag(lock_time,1,null) over(partition by fence,hour(lock_time),bike_id))) as time_gapfrom bike_hour_inc)t1)t2group by t2.fence,t2.bike_id,t2.every_hour order by t2.fence,t2.every_hour,t2.bike_id

    簡(jiǎn)潔版:因?yàn)橥獠樵?xún)使用的是group by后的max聚合,而null是不參與聚合這種的

    樣例19:各拖拉機(jī)在某一省份分小時(shí)段最大未騎行間隔(使用group by+一次窗口函數(shù)? ?簡(jiǎn)介版)

    SQL-- 因?yàn)橥獠樵?xún)使用的是group by后的max聚合,而null是不參與聚合這種的, -- 所以上述代碼還可以繼續(xù)簡(jiǎn)化,不需要對(duì)null進(jìn)行專(zhuān)門(mén)處理 -- 簡(jiǎn)潔版select t1.fence,t1.bike_id,t1.every_hour,max(t1.time_gap) as max_gapfrom(select fence,bike_id,hour(lock_time) as every_hour,unlock_time,lock_time,lag(lock_time,1,null) over(partition by fence,hour(unlock_time),bike_id) as last_lock_time,(unix_timestamp(unlock_time) - unix_timestamp(lag(lock_time,1,null) over(partition by fence,hour(lock_time),bike_id order by unlock_time))) as time_gapfrom bike_hour_inc)t1group by t1.fence,t1.bike_id,t1.every_hour order by t1.fence,t1.every_hour,t1.bike_id

    測(cè)試結(jié)果如下:可以看到除了一些明細(xì)數(shù)據(jù)沒(méi)有(后續(xù)有時(shí)間可以探討再進(jìn)行關(guān)聯(lián)得到所有明細(xì)數(shù)據(jù)),其余的結(jié)果是一致的!!!

    1

    山東

    104

    7

    1748

    2

    湖北

    101

    7

    1018

    3

    湖北

    102

    7

    1928

    4

    湖北

    101

    9

    976

    綜上所述:如果我們只需要的是大致數(shù)據(jù),那么就可以使用上述方法

    思考四:多次窗口使用能否改成一次窗口和group by結(jié)合得到所有明細(xì)數(shù)據(jù)?

    樣例20:各拖拉機(jī)在某一省份分小時(shí)段最大未騎行間隔(group by+窗口 )測(cè)試是否可以得到明細(xì)數(shù)據(jù)

    select t2.fence,t2.bike_id,t2.every_hour,t2.max_gap,t3.* from (select t1.fence,t1.bike_id,t1.every_hour,max(t1.time_gap) as max_gapfrom(select fence,bike_id,hour(lock_time) as every_hour,unlock_time,lock_time,lag(lock_time,1,null) over(partition by fence,hour(unlock_time),bike_id order by unlock_time) as last_lock_time,(unix_timestamp(unlock_time) - unix_timestamp(lag(lock_time,1,null) over(partition by fence,hour(lock_time),bike_id))) as time_gapfrom bike_hour_inc)t1group by t1.fence,t1.bike_id,t1.every_hour )t2 join bike_hour_inc t3 on t2.fence = t3.fence and t2.bike_id = t3.bike_idand t2.every_hour = hour(unlock_time) order by t2.fence,t2.every_hour,t2.bike_id

    測(cè)試結(jié)果:我們發(fā)現(xiàn), group by得到大致數(shù)據(jù)記錄然后再去關(guān)聯(lián),發(fā)現(xiàn)數(shù)據(jù)記錄變多了,這樣說(shuō)明如果group by的不是主鍵,那么就會(huì)數(shù)據(jù)量變多,得不到我們需要的記錄,當(dāng)僅僅group by的是主鍵,才能用這種group by分組再進(jìn)行關(guān)聯(lián)得到所需的最終結(jié)果!

    fence

    bike_id

    every_hour

    max_gap

    fence

    bike_id

    unlock_time

    lock_time

    1

    山東

    104

    7

    1748

    山東

    104

    2022-09-01 07:44:21

    2022-09-01 07:55:13

    2

    山東

    104

    7

    1748

    山東

    104

    2022-09-01 07:02:21

    2022-09-01 07:15:13

    3

    湖北

    101

    7

    1018

    湖北

    101

    2022-09-01 07:32:11

    2022-09-01 07:55:13

    4

    湖北

    101

    7

    1018

    湖北

    101

    2022-09-01 07:12:53

    2022-09-01 07:15:13

    5

    湖北

    101

    7

    1018

    湖北

    101

    2022-09-01 07:03:23

    2022-09-01 07:05:03

    6

    湖北

    101

    7

    1018

    湖北

    101

    2022-09-01 07:56:11

    2022-09-01 07:59:52

    7

    湖北

    102

    7

    1928

    湖北

    102

    2022-09-01 07:02:21

    2022-09-01 07:15:13

    8

    湖北

    102

    7

    1928

    湖北

    102

    2022-09-01 07:47:21

    2022-09-01 07:55:13

    9

    湖北

    101

    9

    976

    湖北

    101

    2022-09-01 09:12:10

    2022-09-01 09:25:53

    10

    湖北

    101

    9

    976

    湖北

    101

    2022-09-01 09:42:09

    2022-09-01 09:45:33

    3.3.4 情景九:連續(xù)出現(xiàn)的數(shù)字

    id

    num

    1

    1

    2

    1

    3

    1

    4

    2

    5

    1

    6

    2

    7

    2

    sql邏輯:

    樣例21:連續(xù)三次出現(xiàn)的數(shù)字

    select distinct num as consecutivenums from (select num,lead(num,1,null) over(order by id) as n1,lead(num,2,null) over(order by id) as n2from shuzi )t1 where t1.num = t1.n1 and t1.n1 = t1.n2

    測(cè)試結(jié)果就是:1

    四:進(jìn)階使用

    4.1 窗口函數(shù)與group by異同點(diǎn)

    4.1.1 窗口函數(shù)與group by 區(qū)別

    窗口函數(shù)分組匯總會(huì)改變返回?cái)?shù)據(jù)的行數(shù),group by 默認(rèn)返回每組中的第一行;而窗口函數(shù)不會(huì)減少返回?cái)?shù)據(jù)行數(shù),只可能是在原始數(shù)據(jù)表新加上一列,來(lái)存放窗口分析得到的值。

    樣例8--group by返回?cái)?shù)據(jù)行數(shù)

    select user_type, count(1) as cnt from order_detail group by user_type

    樣例8測(cè)試結(jié)果:可以看到group by只得到兩條數(shù)據(jù)(一共兩個(gè)分組),而窗口函數(shù)作用后,原來(lái)是幾條數(shù)據(jù),現(xiàn)在還是幾條數(shù)據(jù)。

    user_type

    cnt

    1

    new

    7

    2

    old

    3

    4.1.2 group by去重

    group by可以完成去重效果,但是窗口函數(shù)不能。

    答案:這是不行的,因?yàn)槭褂么翱诤瘮?shù)并沒(méi)有減少數(shù)據(jù)量。那么什么時(shí)候用窗口的時(shí)候不能使用group by呢。參考下面一節(jié)的總結(jié)。

    4.2 collect_list + partition by的特殊用法

    參考: sparksql中collect_list+partitionby的特殊用法 - 百度文庫(kù)

    4.2.1 問(wèn)題提出

    hive或者spark中collect_list一般都是用來(lái)做分組后的合并,也就是說(shuō)經(jīng)常和partition by連用,本節(jié)特定講一下collect_list + partition by的用法。

    問(wèn)題:如何求一個(gè)用戶(hù)的連續(xù)續(xù)課次數(shù)和續(xù)課金額?

    背景:有嚴(yán)格規(guī)定的兩個(gè)課程期次序列:s1,s2,s3,s4和p1,p2,p3,我們規(guī)定滿(mǎn)足如下條件才算是一個(gè)用戶(hù)的續(xù)課;

    a:當(dāng)課程屬于同一課程序列的時(shí)候,必須遵循嚴(yán)格的期次順序,且不得有重復(fù)。如s1,s3,s4,s2,站在s2的角 度看,續(xù)了3次(s3,s4,s2);站在s3的角度看,續(xù)課了1次(s4);

    b:當(dāng)課程屬于不同課程序列的時(shí)候,只要后面跟的是不同的課程序列都算一次,重復(fù)值不算,如. s2,p2,p1,s2,站在s2的角度看,續(xù)費(fèi)了2次(p2,p1);站在p2的角度看,續(xù)費(fèi)了1次(s2)

    4.2.2 解決思路

    1)第一種思路:如果不考慮減少數(shù)據(jù)量,那么對(duì)于用戶(hù)參加的每一次的課程而言,附加一列生成一個(gè)這個(gè)用戶(hù)的全量有序的購(gòu)課記錄就好,只是要記錄一下對(duì)應(yīng)的這門(mén)課在整個(gè)序列中的位置。

    2)第二種思路:最好的方式肯定是對(duì)于每一個(gè)用戶(hù)而言,附加一個(gè)該用戶(hù)在這門(mén)課之后有序的選課記錄,這里也有兩種方式。

    a:自身關(guān)聯(lián)這張表,找出每一個(gè)用戶(hù)買(mǎi)了這門(mén)課之后的所有購(gòu)課記錄和購(gòu)課金額;

    b:如果我們不想再關(guān)聯(lián)一次,那么我們就要考慮一下如何使用collect_list + partition by進(jìn)行處理。

    4.2.3 實(shí)際解決

    給定數(shù)據(jù)

    user_id

    term_id

    pay_time

    1

    s1

    1

    1

    s2

    2

    1

    s3

    3

    1

    s4

    4

    代碼邏輯:

    select user_type, count(1) as cnt from order_detail group by user_type

    測(cè)試結(jié)果:

    user_id

    term_id

    pay_time

    category_list

    1

    s4

    4

    ["s4,"]

    1

    s3

    3

    ["s4,","s3,"]

    1

    s2

    2

    ["s4,","s3,","s2,"]

    1

    s1

    1

    ["s4,","s3,","s2,","s1,"]

    4.3 cube&grouping set這塊

    ?todo 高級(jí)函數(shù)

    GROUPING SETS、GROUPING__ID、CUBE、ROLLUP這幾個(gè)分析函數(shù)通常用于OLAP中,不能累加,而且需要根據(jù)不同維度上鉆和下鉆的指標(biāo)統(tǒng)計(jì),比如,分小時(shí)、天、月的UV數(shù)

    參考:Hive窗口函數(shù)保姆級(jí)教程

    • grouping sets是一種將多個(gè)group by邏輯寫(xiě)在一個(gè)sql語(yǔ)句中的便利寫(xiě)法。等價(jià)于將不同維度的group by結(jié)果集進(jìn)行union all。

    • cube:根據(jù)group by的維度的所有組合進(jìn)行聚合。

    • rollup的使用:是cube的子集,以最左側(cè)的維度為主,從該維度進(jìn)行層級(jí)聚合。

    五:窗口函數(shù)底層運(yùn)行原理

    ?todo

    六:其他注意事項(xiàng)

    參考:

    一文讀懂SQL窗口函數(shù) - 墨天輪

    SQL高級(jí)功能窗口函數(shù)及使用場(chǎng)景 - 知乎

    SQL窗口函數(shù)不懂?五大應(yīng)用場(chǎng)景讓你一步到位_數(shù)據(jù)小斑馬的博客-CSDN博客

    HIVE 窗口及分析函數(shù) 應(yīng)用場(chǎng)景_Data_IT_Farmer的博客-CSDN博客

    Hive之窗口函數(shù)(一文搞懂)_For_dongyang的博客-CSDN博客_hive 窗口函數(shù)

    Hive常用函數(shù)大全(二)(窗口函數(shù)、分析函數(shù)、增強(qiáng)group)_李國(guó)冬的博客-CSDN博客_常用窗口函數(shù)

    總結(jié)

    以上是生活随笔為你收集整理的hive窗口函数最全总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。