前言
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"}]
表內數據如下
explode的使用:
我們只拆解array字段,語句爲select explode(split(goods_id,’,’)) as goods_id from explode_lateral_view;
結果如下
拆解map字段
語句爲select explode(split(area,’,’)) as area from explode_lateral_view;
我們會得到如下結果:
拆解json字段
這個時候要配合一下get_json_object
我們想獲取所有的monthSales,第一步我們先把這個字段拆成list,並且拆成行展示:
select explode(split(regexp_replace(regexp_replace(sale_info,’\[\{’,’’),’}]’,’’),’},\{’)) as sale_info from explode_lateral_view;
然後我們想用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;
其中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;
也是三個表笛卡爾積的結果
現在我們解決一下上面的問題,從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;
最終,我們可以通過下面的句子,把這個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;
原文鏈接:https://blog.csdn.net/guodong2k/article/details/79459282