HIVE 處理json結構數據
Table of Contents
1 問題
寬表存儲數據,必然會面臨一個問題:一對多,數據是N倍的存儲。將會多占用N倍空間。而這些源數據入庫的時候,在文件中存放時,也可能使用json格式。
遇到這種情況,使用json_tuple來解析json數據是一個非常不錯的方法。如果只是查詢json中某一個Key的值,那么使用get_json_object是個更好的選擇。
2 知識點
2.1 lateral view
Lateral view 通常和split, explode等udtf一起封裝使用,它能夠將一行數據拆分成多行數據,在此基礎上可以對拆分后的數據進行聚合.
該函數的作用就是通過udtf相關函數把一行拆分成一行或者多行的結果進行聚合,產生一個支持別名表的虛擬表。
語法結構如下:
ATERAL VIEW udtf(expression) alias_table_name AS columns(',', columns)*
2.2 explode
explode 將數組、列表、MAP中每個元素轉換為同一列的不同行,可以理解為行轉列,處理的結果以表格的形式輸出。explode 只能處理數組(列表)或者map結構。 使用方法非常簡單:explode(數據或者列表或者MAP結構數據)。
比如數組: [1,2,3].可以轉換為
1 2 3
而map結構,比如字典:{'a':1,'b':2,'c':3} 可以轉換成:
a 1 b 2 c 3
各位可以執行下面兩個查詢語句塊,了解explode的效果:
select array(1,2,3); select explode(array(1,2,3));
下面通過str_to_map1 來實現map結構
select str_to_map(concat('a:',1,'&b:',2,'&c:',3),'&',':'); select str_to_map(concat('a:',1,'^b:',2,'^c:',3),'\\^',':'); select explode(str_to_map(concat('a:',1,'&b:',2,'&c:',3),'&',':'));
2.3 json_tuple
json_tuple 從json格式數據中,通過指定的keys 來讀取相應的values. 讀取的結果以表格的形式輸出。語法結構如下:
使用方法如下:json_tuple(數據源,json中的key1,key2,….). 比如:
select json_tuple('{"a":1,"b":2,"c":3}','a','b');
3 示例
下面是將json數據轉換成表結構的示例。
-
測試
-- 建表 drop table if exists jsontest; CREATE TABLE IF NOT EXISTS jsonTest (teacher_name varchar(10), major varchar(10), students_info string comment "學生信息" ) comment "學生課程信息" row format serde 'org.apache.hive.hcatalog.data.JsonSerDe' LOCATION 'hdfs://nameservice1/user/hive/warehouse/bigdata.db/jsontest'; insert into jsontest values ('t1','語文','{"grade":1,"info":{"name":"xinzi","age":14,"sex":"M"}}|{"grade":3,"info":{"name":"lisi","age":14,"sex":"M"}}'), ('t2','maths','{"grade":2,"info":{"name":"zhangs","age":14,"sex":"F"}}') ; -- 查看已有數據 select row_number() over() , a.* from jsontest a; -- 創建視圖 drop view if exists v_jsontest; create view if not exists v_jsontest as select teacher_name,major,a.grade,b.name,b.age,b.gender from jsontest lateral view explode(split(students_info,'\\|')) stabcdefghi as stin lateral view json_tuple(stin,'grade','info') a as grade,info lateral view json_tuple(a.info,'name','age','sex') b as name,age,gender;
-
原表數據
hive> select * from jsontest; OK t1 語文 {"grade":1,"info":{"name":"xinzi","age":14,"sex":"M"}}|{"grade":3,"info":{"name":"lisi","age":14,"sex":"M"}} t2 maths {"grade":2,"info":{"name":"zhangs","age":14,"sex":"F"}} Time taken: 0.054 seconds, Fetched: 2 row(s)
-
轉換后結果
hive> select * from v_jsontest; .......... OK t1 語文 1 xinzi 14 M t1 語文 3 lisi 14 M t2 maths 2 zhangs 14 F Time taken: 12.933 seconds, Fetched: 3 row(s)
Footnotes:
關於map,可以通過函數str_to_map來實現,也可以在建表時定義。這里使用str_to_map 來進行測試. str_to_map(字符串參數, 分隔符1, 分隔符2),使用兩個分隔符將文本拆分為鍵值對。 分隔符1將文本分成K-V對,分隔符2分割每個K-V對。對於分隔符1默認分隔符是 ',',對於分隔符2默認分隔符是 '='。
Created: 2020-04-09 Thu 13:48