好了,接下來咱們來看看如何在Hive中實現(xiàn)一行轉(zhuǎn)多行的操作,主要介紹explode和posexplode函數(shù)的使用。
沿用上一節(jié)的數(shù)據(jù),從簡單到復(fù)雜,咱們一步步來。
1、數(shù)據(jù)介紹
先看下我們的數(shù)據(jù),主要包括三列,分別是班級、姓名以及成績,數(shù)據(jù)表名是default.classinfo。

2、單列Explode
首先來看下最基本的,我們?nèi)绾伟裺tudent這一列中的數(shù)據(jù)由一行變成多行。這里需要使用split和explode,并結(jié)合lateral view實現(xiàn)。代碼如下:
select
class,student_name
from
default.classinfo
lateral view explode(split(student,',')) t as student_name
結(jié)果如下:

3、單列Posexplode
接下來,我們想要給每個同學(xué)來一個編號,假設(shè)編號就按姓名的順序,此時我們要用到另一個hive函數(shù),叫做posexplode,代碼如下:
select
class,student_index + 1 as student_index,student_name
from
default.classinfo
lateral view posexplode(split(student,',')) t as student_index,student_name
這里select時對編號+1主要是因為編號是從0開始的,結(jié)果如下:

4、多列Explode
好了,我們繼續(xù)前進(jìn)。這次我們想基于兩列explode,同時能夠使學(xué)生和其成績能夠匹配,即期望的效果如下:

顯然我們要對兩列進(jìn)行explode,先試試行不行:
select
class,student_name,student_score
from
default.classinfo
lateral view explode(split(student,',')) sn as student_name
lateral view explode(split(score,',')) sc as student_score
結(jié)果如下:

好像是不太行,如果我們分別對兩列進(jìn)行explode的話,假設(shè)每列都有三個值,那么最終會變成3 * 3 = 9行。但我們想要的結(jié)果只有三行。此時我們可以進(jìn)行兩次posexplode,姓名和成績都保留對應(yīng)的序號,即使變成了9行,我們通過where條件只保留序號相同的行即可。代碼如下:
select
class,student_name,student_score
from
default.classinfo
lateral view posexplode(split(student,',')) sn as student_index_sn,student_name
lateral view posexplode(split(score,',')) sc as student_index_sc,student_score
where
student_index_sn = student_index_sc
此時結(jié)果就對了:

好了,到這里本應(yīng)該就結(jié)束了,假設(shè)我們又想對同學(xué)的成績進(jìn)行一下排名該怎么做呢?當(dāng)然是借助rank函數(shù)啦(row_number函數(shù)對于相同的成績也會賦予不同的排名,所以我們選擇rank函數(shù),關(guān)于二者的區(qū)別我們后續(xù)再細(xì)講):
select
class,
student_name,
student_score,
rank() over(partition by class order by student_score desc) as student_rank
from
default.classinfo
lateral view posexplode(split(student,',')) sn as student_index_sn,student_name
lateral view posexplode(split(score,',')) sc as student_index_sc,student_score
where
student_index_sn = student_index_sc
order by class,student_rank
結(jié)果符合我們預(yù)期:

好了,本文就到這里了!下期再見!