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

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

生活随笔

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

编程问答

Hive开窗函数总结

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

背景:
平常我們使用 hive或者 mysql時(shí),一般聚合函數(shù)用的比較多。但對(duì)于某些偏分析的需求,group by可能很費(fèi)力,子查詢(xún)很多,這個(gè)時(shí)候就需要使用窗口分析函數(shù)了~
注:hiveoracle提供開(kāi)窗函數(shù),mysql8之前版本不提供,但Oracle發(fā)布的 MySQL 8.0版本支持窗口函數(shù)(over)和公用表表達(dá)式(with)這兩個(gè)重要的功能!


版本:Hive 1.1.0 + cdh5.13.0


一、介紹

分析函數(shù)用于計(jì)算基于組的某種聚合值,它和聚合函數(shù)的不同之處是:對(duì)于每個(gè)組返回多行,而聚合函數(shù)對(duì)于每個(gè)組只返回一行

開(kāi)窗函數(shù)指定了分析函數(shù)工作的數(shù)據(jù)窗口大小,這個(gè)數(shù)據(jù)窗口大小可能會(huì)隨著行的變化而變化!到底什么是數(shù)據(jù)窗口?后面舉例會(huì)詳細(xì)講到!

1. 基礎(chǔ)結(jié)構(gòu):

分析函數(shù)(如:sum(),max(),row_number()...) + 窗口子句(over函數(shù))

2. over函數(shù)寫(xiě)法:
  over(partition by cookieid order by createtime) 先根據(jù)cookieid字段分區(qū),相同的cookieid分為一區(qū),每個(gè)分區(qū)內(nèi)根據(jù)createtime字段排序(默認(rèn)升序)
  
注:不加 partition by 的話(huà)則把整個(gè)數(shù)據(jù)集當(dāng)作一個(gè)分區(qū),不加 order by的話(huà)會(huì)對(duì)某些函數(shù)統(tǒng)計(jì)結(jié)果產(chǎn)生影響,如sum()

3. 測(cè)試數(shù)據(jù):

測(cè)試表test1只有三個(gè)字段 cookieid、createtime、pv

4. 窗口含義:

SELECT cookieid,createtime,pv, SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默認(rèn)為從起點(diǎn)到當(dāng)前行 SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --從起點(diǎn)到當(dāng)前行,結(jié)果同pv1 SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv3, --當(dāng)前行+往前3行 SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv4, --當(dāng)前行+往前3行+往后1行 SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv5 ---當(dāng)前行+往后所有行 FROM test1;

結(jié)果:

cookieid createtime pv pv1 pv2 pv3 pv4 pv5 a 2017-12-01 3 3 3 3 3 3 b 2017-12-00 3 3 3 3 3 3 cookie1 2017-12-10 1 1 1 1 6 26 cookie1 2017-12-11 5 6 6 6 13 25 cookie1 2017-12-12 7 13 13 13 16 20 cookie1 2017-12-13 3 16 16 16 18 13 cookie1 2017-12-14 2 18 18 17 21 10 cookie1 2017-12-15 4 22 22 16 20 8 cookie1 2017-12-16 4 26 26 13 13 4 cookie2 2017-12-12 7 7 7 7 13 14 cookie2 2017-12-16 6 13 13 13 14 7 cookie2 2017-12-24 1 14 14 14 14 1 cookie3 2017-12-22 5 5 5 5 5 5

注:這些窗口的劃分都是在分區(qū)內(nèi)部!超過(guò)分區(qū)大小就無(wú)效了

相信大家看了后就會(huì)明白,如果不指定ROWS BETWEEN,默認(rèn)統(tǒng)計(jì)窗口為從起點(diǎn)到當(dāng)前行;如果不指定ORDER BY,則將分組內(nèi)所有值累加;

關(guān)鍵是理解 ROWS BETWEEN 含義,也叫做window子句
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:當(dāng)前行
UNBOUNDED:無(wú)邊界,UNBOUNDED PRECEDING 表示從最前面的起點(diǎn)開(kāi)始, UNBOUNDED FOLLOWING:表示到最后面的終點(diǎn)
–其他AVG,MIN,MAX,和SUM用法一樣


二、SUM 函數(shù)

select cookieid,createtime,pv, sum(pv) over(PARTITION BY cookieid ORDER BY createtime) as pv1 FROM test1


首先 PARTITION BY cookieid,根據(jù)cookieid分區(qū),各分區(qū)之間默認(rèn)根據(jù)字典順序排序,ORDER BY createtime,指定的是分區(qū)內(nèi)部的排序,默認(rèn)為升序

我們可以清晰地看到,窗口函數(shù)和聚合函數(shù)的不同,sum()函數(shù)可以根據(jù)每一行的窗口返回各自行對(duì)應(yīng)的值,有多少行記錄就有多少個(gè)sum值,而group by只能計(jì)算每一組的sum,每組只有一個(gè)值!

其中sum()計(jì)算的是分區(qū)內(nèi)排序后一個(gè)個(gè)疊加的值,和order by有關(guān)

如果不加 order by會(huì)咋樣:

select cookieid,createtime,pv, sum(pv) over(PARTITION BY cookieid) as pv1 FROM test1


可以看到,如果沒(méi)有order by,不僅分區(qū)內(nèi)沒(méi)有排序,sum()計(jì)算的pv也是整個(gè)分區(qū)的pv

注:max()函數(shù)無(wú)論有沒(méi)有order by 都是計(jì)算整個(gè)分區(qū)的最大值


三、NTILE 函數(shù)

NTILE(n),用于將分組數(shù)據(jù)按照順序切分成n片,返回當(dāng)前切片值

注1:如果切片不均勻,默認(rèn)增加第一個(gè)切片的分布
注2:NTILE不支持ROWS BETWEEN

SELECT cookieid,createtime,pv, NTILE(2) OVER(PARTITION BY cookieid ORDER BY createtime) AS ntile1, --分組內(nèi)將數(shù)據(jù)分成2片 NTILE(3) OVER(PARTITION BY cookieid ORDER BY createtime) AS ntile2, --分組內(nèi)將數(shù)據(jù)分成3片 NTILE(4) OVER(PARTITION BY cookieid ORDER BY createtime) AS ntile3 --將所有數(shù)據(jù)分成4片 FROM test1

用法舉例:
統(tǒng)計(jì)一個(gè)cookie,pv數(shù)最多的前1/3的天:

SELECT cookieid,createtime,pv, NTILE(3) OVER(PARTITION BY cookieid ORDER BY pv DESC) AS ntile FROM test1;

取 ntile = 1 的記錄,就是我們想要的結(jié)果!


四、ROW_NUMBER 函數(shù)

ROW_NUMBER() 從1開(kāi)始,按照順序,生成分組內(nèi)記錄的序列

ROW_NUMBER() 的應(yīng)用場(chǎng)景非常多,比如獲取分組內(nèi)排序第一的記錄、獲取一個(gè)session中的第一條refer等。

SELECT cookieid,createtime,pv, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn FROM test1;


五、RANK 和 DENSE_RANK 函數(shù)

RANK() 生成數(shù)據(jù)項(xiàng)在分組中的排名,排名相等會(huì)在名次中留下空位
DENSE_RANK() 生成數(shù)據(jù)項(xiàng)在分組中的排名,排名相等會(huì)在名次中不會(huì)留下空位

我們把 rankdense_rankrow_number三者對(duì)比,這樣比較清晰:

SELECT cookieid,createtime,pv, RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rank1, DENSE_RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS d_rank2, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn3 FROM test1


六、CUME_DIST 函數(shù)

cume_dist 返回小于等于當(dāng)前值的行數(shù)/分組內(nèi)總行數(shù)

比如,我們可以統(tǒng)計(jì)小于等于當(dāng)前薪水的人數(shù),所占總?cè)藬?shù)的比例

SELECT cookieid,createtime,pv, round(CUME_DIST() OVER(ORDER BY pv),2) AS cd1, round(CUME_DIST() OVER(PARTITION BY cookieid ORDER BY pv),2) AS cd2 FROM test1;


注:cd1沒(méi)有partition,所有數(shù)據(jù)均為1組!


七、PERCENT_RANK 函數(shù)

percent_rank 分組內(nèi)當(dāng)前行的RANK值-1/分組內(nèi)總行數(shù)-1

注:一般不會(huì)用到該函數(shù),可能在一些特殊算法的實(shí)現(xiàn)中可以用到吧

SELECT cookieid,createtime,pv, PERCENT_RANK() OVER(ORDER BY pv) AS rn1 from test1


八、LAG 和 LEAD 函數(shù)

LAG(col,n,DEFAULT) 用于統(tǒng)計(jì)窗口內(nèi)往上第n行值

第一個(gè)參數(shù)為列名,第二個(gè)參數(shù)為往上第n行(可選,默認(rèn)為1),第三個(gè)參數(shù)為默認(rèn)值(當(dāng)往上第n行為NULL時(shí)候,取默認(rèn)值,如不指定,則為NULL)

SELECT cookieid,createtime,pv, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, LAG(createtime,1,'1970-01-01') OVER(PARTITION BY cookieid ORDER BY createtime) AS lag1, LAG(createtime,2) OVER(PARTITION BY cookieid ORDER BY createtime) AS lag2 FROM test1;

LEAD 函數(shù)則與 LAG 相反:
LEAD(col,n,DEFAULT) 用于統(tǒng)計(jì)窗口內(nèi)往下第n行值

第一個(gè)參數(shù)為列名,第二個(gè)參數(shù)為往下第n行(可選,默認(rèn)為1),第三個(gè)參數(shù)為默認(rèn)值(當(dāng)往下第n行為NULL時(shí)候,取默認(rèn)值,如不指定,則為NULL)


九、FIRST_VALUE 和 LAST_VALUE 函數(shù)

FIRST_VALUE 取分組內(nèi)排序后,截止到當(dāng)前行,第一個(gè)值

SELECT cookieid,createtime,pv, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, FIRST_VALUE(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS first FROM test1;

LAST_VALUE 函數(shù)則相反:
LAST_VALUE 取分組內(nèi)排序后,截止到當(dāng)前行,最后一個(gè)值

這兩個(gè)函數(shù)還是經(jīng)常用到的(往往和排序配合使用),比較實(shí)用!


參考文章:http://lxw1234.com/archives/category/hive

總結(jié)

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

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