場景一:分組求TopN
先看數(shù)據(jù):
好像把小編的數(shù)學(xué)成績暴露了橡淆,現(xiàn)在需要求每一門科目,成績排名前兩名的同學(xué)逸爵。
使用HiveSQL常用的方式為:
select
*
from
(select
item
,name
,score
,row_number() over(partition by item order by score desc) rank
from table
groupby item) a
where rank<=2;
輸出結(jié)果為:
解析:row_number()函數(shù)基于over對象分組师倔、排序的記過,為每一行分組記錄返回一個序號趋艘,該序號從1開始,依次遞增瓷胧,遇到新組則重新從1開始。也就是說搓萧,該函數(shù)計算的值表示每組內(nèi)部排序后的順序編號遇八。
然后在語句中加入限制條件rank<=2來篩選具體選取top幾。從最終的結(jié)果可以看出刃永,語文成績考試前兩名的同學(xué)分別是建國和小編、數(shù)學(xué)成績排名前兩名的同學(xué)分別是建國和狗剩斯够。
場景二:行轉(zhuǎn)列/列轉(zhuǎn)行
數(shù)據(jù)如下:
現(xiàn)在需要轉(zhuǎn)換為
使用hive實現(xiàn)需求的話读规,可以使用:
select
name,
sum(case when item=數(shù)學(xué) then score end) as math,
sum(case when item=英語 then score end) as english,
from table
group by name
解析:首先寫出select name from table group by name, 因為select后有幾個字段,最終輸出就是幾個字段燃少,所以我們需要把目標數(shù)據(jù)的”math”和“english”兩個字段想辦法得出來。
之后可以對item字段所有枚舉的結(jié)果進行case when判斷阵具,將score填值進入,因為最后我們需要對name做一下聚合阳液,需要明確的是一般選取字段一定要出現(xiàn)在groupby里面。
聚合函數(shù)可以不用帘皿,所以我們在外面套一層sum做聚合,這樣得到sum的結(jié)果和單人得分結(jié)果是一致的鹰溜,因為我們以name做了一遍聚合,而每個用戶對一門課程只有一個成績曹动,所以這樣就可以得到最終結(jié)果。
那么最后如果需要將“表-4”的內(nèi)容轉(zhuǎn)換為“表-3”的內(nèi)容應(yīng)該怎么做呢仁期?
一種比較好的方式是這樣:
select table_4.name,
a.item,
a.score
from table_4
lateral view explode(
str_to_map(concat('math=',math,'&english=',english),'&','=')
) a as item,score;
解析:首先使用str_to_map函數(shù)將math字段與english字段拼接后的結(jié)果轉(zhuǎn)換為map類型跛蛋,然后通過側(cè)視圖和explode函數(shù)將其爆炸開,給生成的臨時側(cè)視圖一個名字赊级,取名a并給列名取名為item,score,因為explode(map)爆炸的結(jié)果是每一個item為行理逊,key為1列橡伞,value為1列,這樣就恰好形成我們想要的結(jié)果。這個示例理解起來稍微有點難度兑徘,大家不熟悉這些函數(shù)的用法的話,可以首先熟悉一下挂脑。