hive 的lateral view 與 explode函數詳解

前言

explode與lateral view在關係型數據庫中本身是不該出現的,因爲他的出現本身就是在操作不滿足第一範式的數據(每個屬性都不可再分),
本身已經違背了數據庫的設計原理(不論是業務系統還是數據倉庫系統),不過大數據技術普及後,很多類似pv,uv的數據,在業務系統中是存貯在非關係型數據庫中,
用json存儲的概率比較大,直接導入hive爲基礎的數倉系統中,就需要經過ETL過程解析這類數據,explode與lateral view在這種場景下大顯身手。

EXPLODE

explode作用是處理map結構的字段,使用案例如下(hive自帶map,struct,array字段類型,但是需要先定義好泛型,所以在此案例不使用):

舉例:

建表語句:
drop table explode_lateral_view;
create table explode_lateral_view
(`area` string,
`goods_id` string,
`sale_info` string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '|'
STORED AS textfile;

導入數據:
a:shandong,b:beijing,c:hebei|1,2,3,4,5,6,7,8,9|[{"source":"7fresh","monthSales":4900,"userCount":1900,"score":"9.9"},{"source":"jd","monthSales":2090,"userCount":78981,"score":"9.8"},{"source":"jdmart","monthSales":6987,"userCount":1600,"score":"9.0"}]

表內數據如下

img

explode的使用:

我們只拆解array字段,語句爲select explode(split(goods_id,’,’)) as goods_id from explode_lateral_view;
結果如下

img

拆解map字段

語句爲select explode(split(area,’,’)) as area from explode_lateral_view;
我們會得到如下結果:

img

拆解json字段

這個時候要配合一下get_json_object

我們想獲取所有的monthSales,第一步我們先把這個字段拆成list,並且拆成行展示:
select explode(split(regexp_replace(regexp_replace(sale_info,’\[\{’,’’),’}]’,’’),’},\{’)) as sale_info from explode_lateral_view;

img

然後我們想用get_json_object來獲取key爲monthSales的數據:
select get_json_object(explode(split(regexp_replace(regexp_replace(sale_info,’\[\{’,’’),’}]’,’’),’},\{’)),’$.monthSales’) as sale_info from explode_lateral_view;

注意:

然後掛了FAILED: SemanticException [Error 10081]: UDTF’s are not supported outside the SELECT clause, nor nested in expressions
UDTF explode不能寫在別的函數內
如果你這麼寫,想查兩個字段,select explode(split(area,’,’)) as area,good_id from explode_lateral_view;
會報錯FAILED: SemanticException 1:40 Only a single expression in the SELECT clause is supported with UDTF’s. Error encountered near token ‘good_id’
使用UDTF的時候,只支持一個字段,這時候就需要LATERAL VIEW出場了

LATERAL VIEW

側視圖的意義是配合explode(或者其他的UDTF),一個語句生成把單行數據拆解成多行後的數據結果集。
select goods_id2,sale_info from explode_lateral_view LATERAL VIEW explode(split(goods_id,’,’))goods as goods_id2;

img

其中LATERAL VIEW explode(split(goods_id,’,’))goods相當於一個虛擬表,與原表explode_lateral_view笛卡爾積關聯。
也可以多重使用
select goods_id2,sale_info,area2
from explode_lateral_view
LATERAL VIEW explode(split(goods_id,’,’))goods as goods_id2
LATERAL VIEW explode(split(area,’,’))area as area2;
也是三個表笛卡爾積的結果

img

現在我們解決一下上面的問題,從sale_info字段中找出所有的monthSales並且行展示
select get_json_object(concat(’{’,sale_info_r,’}’),’$.monthSales’) as monthSales from explode_lateral_view
LATERAL VIEW explode(split(regexp_replace(regexp_replace(sale_info,’\[\{’,’’),’}]’,’’),’},\{’))sale_info as sale_info_r;

img

最終,我們可以通過下面的句子,把這個json格式的一行數據,完全轉換成二維表的方式展現

select get_json_object(concat('{',sale_info_1,'}'),'$.source') as source,
     get_json_object(concat('{',sale_info_1,'}'),'$.monthSales') as monthSales,
     get_json_object(concat('{',sale_info_1,'}'),'$.userCount') as monthSales,
     get_json_object(concat('{',sale_info_1,'}'),'$.score') as monthSales
  from explode_lateral_view 

LATERAL VIEW explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{'))sale_info as sale_info_1;

img

原文鏈接:https://blog.csdn.net/guodong2k/article/details/79459282

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