hive中將單行拆分成多行總結

hive中將單行拆分成多行

初始值:

id name mobiles
1 jim 139,177,158

想得到的結果:

id name mobiles
1 jim 139
1 jim 177
1 jim 158

創建測試數據

CREATE TABLE fwj.customer
(
id STRING,
name STRING,
mobiles STRING);

INSERT INTO fwj.customer
SELECT '1','jim','139,177,158' FROM system.dual;

1.最笨的辦法:

邏輯簡單,寫法粗暴,可拓展性爲0。

SELECT a.id,a.name,substr(a.mobiles,1,3) mobiles FROM fwj.customer a 
UNION ALL
SELECT a.id,a.name,substr(a.mobiles,5,3) mobiles FROM fwj.customer a 
UNION ALL
SELECT a.id,a.name,substr(a.mobiles,9,3) mobiles FROM fwj.customer a 

result:
id    mobiles    name
1    189        jim
1    177        jim
1    158        jim

2. 第二種方法

仔細看看這個mobiles字段,其實我們只要將這個字段中用逗號間隔的值拆開到每一列,然後再和原表關聯就能得到我們想要的答案了。在oracle中有列傳行,hive中也有類似的操作。

SELECT b.id,a.mobiles,b.name FROM (
SELECT explode(split(t.mobiles,',')) mobiles FROM fwj.customer t )a ,  fwj.customer b;

result:
id    mobiles    name
1    189        jim
1    177        jim
1    158        jim

這裏會用到兩個函數。
split(str,sep):
該函數的作用是拆分指定分隔符分割的字符串,返回一個列表。
如:

SELECT split(a.mobiles,',') FROM  fwj.customer a;

result:
["189","177","158"]

explode(arr):
該函數是一個表生成函數。輸入一個列表參數,將列表中的每個值都轉換爲一行。
如:

SELECT explode(plit(a.mobiles,',')) mobiles FROM  fwj.customer a;

result:

mobiles
189
177
158

3.第三種方法

問題雖然解決了,但還不夠完美,表被讀了兩次。能不能一次就能取出我們想要的結果呢?

再來優化一下:
···
SELECT t.id,t.name,explode(split(t.mobiles,',')) mobiles FROM fwj.customer t
···
可惜不行,explode 這類UDTF函數不支持和其他字段一塊被select。

不過,hive提供了 lateral view 側視圖 這個功能。

SELECT a.id,a.name,mob.mobile  FROM fwj.customer a lateral view explode(split(a.mobiles,',')) mob AS mobile;

result:
id    mobiles    name
1    189        jim
1    177        jim
1    158        jim

可以理解成在一次查詢中 先生成了一個視圖 mob 包含了行轉列後的數據,之後從mob 中取出轉換後的數據,其他字段仍舊從原表中取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章