在正式學習之前,我們需要明確窗函數和分組的區別。它們在功能上相似,但本質上是不同的。
1.分組將改變表格的結構,但窗口函數不會改變表格的結構。例如,原始表有10行數據,分成兩組後只有兩行,而窗口函數仍然返回十行數據。
2.分組只能查詢分組後的字段,包括分組字段(組名)和聚合函數字段。window函數對查詢字段沒有限制,也就是說,它可以查詢原始表中的任何字段,以及由window函數添加的壹列新值。
好了,現在讓我們壹起進入窗口函數的世界吧~
本節課的主要內容:
1,累積計算窗口函數
(1)sum(……)over(……)
(2)平均(……)超過(……)
③語法總結
2.分區排序窗口函數
(1)行編號()
②排名()
(3)密集秩()
3.切片排序窗口函數
(1)n結束(……)
4.遷移分析窗口功能
5.關鍵練習
在制作報表時,經常會遇到截止到某個月的累計值的計算,通常可以通過EXCEL中的函數來實現。
那麽在HiveSQL中,如何實現這個累計值的計算呢?那就是使用窗口功能!
關於窗口功能的壹些說明:
需求分析:既然要按月累計,那麽首先要將2018中的每筆交易時間轉換為月份並通過分組和聚合進行計算,得到2018中的每月付款金額匯總表,然後使用窗口函數基於此表進行累計計算。
2018月供金額匯總表:
然後使用窗口功能進行每月累積:
年度總結。
這個需求比1的需求多壹個需求,那就是年度總結。然後我們只需要在最後壹個需求的子查詢中添加壹個年份字段。
描述:
Partition by in 1及以上在窗口中起到分組數據的作用。實際上,添加partition by後,可以理解為將其劃分為多個窗口,並在每個窗口中進行累積計算或分區。
如果不按年份添加分區,運行結果將簡單地按月份分組:
2.累積的順序是什麽,升序ASC和降序desc;默認值為升序。
大家在看股票的時候經常會看到這種k線圖,這種k線圖經常被用作7日和30日移動平均線的走勢圖。如何使用窗口函數計算移動平均線?
需求分析:此需求要求每月近三個月的移動平均支付金額。這裏需要用到壹個新的知識點。在窗口函數avg over‘s order by a . month後,添加壹句“Rows between 2 previous and current row”以設置計算移動平均值的範圍。這句話的意思是包括這壹行和前兩行。其他部分的寫法和前面的需求差不多。首先,取出每月支付金額的總和2018,然後使用窗口函數找到移動平均線。
註意:
sum(…A…)over(partition by…B…order by…C…行在…D1…和…D2…之間)
avg(…A…)over(分區依據…B…排序依據…C…d 1…和…D2…之間的行)
答:要處理的字段的名稱
b:分組的字段名
c:排序字段名稱
d:計算的行的範圍
未綁定的前壹行和當前行之間的行
-包括這壹行和所有以前的行。
當前行和未綁定的後續行之間的行
-包括此行和所有後續行。
前3行和當前行之間的行
——包括行內和前三線。
前面3行和後面1行之間的行
——從前三行到下壹行(5行)
max(……)over(partition by……order by……行在……和……之間)
min(……)over(partition by……order by……行在……和……之間)
行數()、秩()、密度秩()
用法:這三個函數的作用是返回對應規則的排序序號。
row _ number()over(partition by…A…order by…B…)
rank()超過(分區依據…A…排序依據…B…)
dense _ rank()over(partition by…A…order by…B…)
a:分組的字段名稱
b:排序字段名稱
註意:這三個函數的括號中沒有字段名!
Row_number:它將為查詢找到的每壹行記錄生成壹個序列號,這些記錄將依次排序,不會重復。
排名與排名。Dense_rank:在每個分組內,rank()是跳躍排序,當有兩個第壹個時,第三個跟隨,而dense_rank()是連續排序,當有兩個第壹個時,第二個仍然跟隨。
示例練習:
再次熟悉user_trade的表結構:
需求分析:先限定時間範圍,然後按user_name分組,分組後選擇user_name,並計算每個用戶的goods_category數量(記得區分重復項),然後用window函數對goods_category數量進行排序。當然,選擇哪種排序方法取決於具體要求。在這裏,我們可以用三種方法來嘗試結果:
註意:窗口函數中的order by字段不能由select中的字段重命名,因為兩者是同時執行的。
需求分析:首先使用窗口函數計算並排序每個用戶在2019年的總支付金額,然後以此為子查詢提取排名為10、20和30的用戶名、總支付金額和排名順序。企業壹般使用dense_rank進行排序,所以我們這裏直接使用dense_rank。
2019每位用戶總支付金額排名:
付款金額在2019中排名為10、20和30的用戶:
分區依據…A…排序依據…B…)
n:分割的切片數量。
a:分組的字段名稱
b:排序字段名稱
需求分析:這個需求非常簡單,只需將需求5第壹步中的排序窗口功能變成切片即可。請註意,時間篩選條件變為2019 1月。
需求分析:前10%,即a * * *分為10組,取1組。因此,讓我們先進行分組:
然後看第壹組:
說明:Lag和Lead分析函數可以提取同壹字段的前n行數據(Lag)和後n行數據(Lead)作為同壹查詢中的獨立列。
在實際應用中,如果要計算今天和昨天的差值,滯後和超前函數的應用尤為重要。當然,這種操作可以通過表自連接來實現,但LAG和LEAD比left join和right join等自連接更高效,SQL語句更簡潔。
lag(exp _ str,offset,defval)over(partion by……order by……)
lead(exp _ str,offset,defval)over(partion by……,order by ……)
lag()函數示例:
lead()函數示例:
需求分析:首先從user_trade表中取出每個用戶的付款時間,將每個用戶放在壹個窗口中,按付款時間排序,並取出offset列:lead(dt,1,dt)over(partition by user _ name order by dt)。然後基於子查詢,篩選出時間間隔大於100天的用戶並計算數量。
註意:如果上面的遷移分析函數寫成lead(dt,1,dt),就沒必要加上下面的dt is not null了,因為如果有默認值,間隔就是0,肯定不滿足條件。
需求分析:
步驟1:兩個表user_trade和user_info用於此需求。前者取支付時間和金額,後者取城市和性別。首先,這兩個表基於用戶名左連接,並取出相應的字段,並按窗口函數排序:
該步驟的運行結果如下:
第二步:取出TOP3:
需求分析:
步驟1:這個需求還使用了兩個表,user_refund和user_info。我們先把每個退款用戶的退款金額和手機品牌拿出來,用窗口功能切片排序,25%分成四塊:
註意:這裏之所以要添加WHERE dt不為null是因為user_refund是壹個分區表,分區表應該限制分區字段,否則hive會報錯。
第二步:選擇前25%,也就是第壹部電影:
最後,添加壹個從hive導出結果數據的命令:
這堂課就到這裏。整個練習下來,我真的掉了半條命。窗口功能確實很難,但掌握方法,多練習,學會拆解需求,循序漸進地做,可以明顯降低難度。希望我以後能用上這麽復雜的技能,哈哈~!