hive中的lateral view 与 explode函数的使用

Hive中Explode与LateralView详解

explode与lateral view在关系型数据库中本身是不该出现的,因为他的出现本身就是在操作不满足第一范式的数据(每个属性都不可再分),
本身已经违背了数据库的设计原理(不论是业务系统还是数据仓库系统),不过大数据技术普及后,很多类似pv,uv的数据,在业务系统中是存贮在非关系型数据库中,
用json存储的概率比较大,直接导入hive为基础的数仓系统中,就需要经过ETL过程解析这类数据,explode与lateral view在这种场景下大显身手。


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;


————————————————
版权声明:本文为优快云博主「guodong2k」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/guodong2k/article/details/79459282

Hive SQL 中,`LATERAL VIEW EXPLODE` 是用于将数组或映射类型的列展开为多行记录的重要机制。然而,Impala SQL 并不支持 `LATERAL VIEW` 语法,因此需要采用不同的方法来实现相同的效果。 在 Impala 中,可以使用 `CROSS JOIN UNNEST` 语法来替代 Hive 中的 `LATERAL VIEW EXPLODE` 功能。Impala 的 `UNNEST` 函数可以将数组展开为多行,同时支持原始表的字段进行连接。 ### 语法对比 #### Hive SQL 示例 ```sql SELECT id, name, course FROM student LATERAL VIEW explode(courses) courseTable AS course; ``` 其中 `courses` 是一个数组类型的列,该语句将每个学生他们所选的每门课程拆分为一行记录 [^1]。 #### Impala SQL 替代语法 ```sql SELECT id, name, course FROM student CROSS JOIN UNNEST(courses) AS t(course); ``` Impala 中的 `CROSS JOIN UNNEST` 实现了 Hive 中 `LATERAL VIEW EXPLODE` 相同的功能,将数组列 `courses` 展开为多个行,并保留原始表中的其他字段 [^2]。 ### 映射类型处理 如果需要处理映射类型(Map),在 Hive 中可以使用 `EXPLODE(map)` 并通过 `AS (key, value)` 来提取键值对。例如: ```sql SELECT id, name, key, value FROM student LATERAL VIEW explode(attributes) attrTable AS key, value; ``` 在 Impala 中,可以通过 `UNNEST` `TABLE` 函数结合来实现: ```sql SELECT id, name, key, value FROM student CROSS JOIN UNNEST(MAP_KEYS(attributes)) AS k(key) CROSS JOIN UNNEST(MAP_VALUES(attributes)) AS v(value) WHERE POSITION = k.pos; ``` 这里 `MAP_KEYS` 和 `MAP_VALUES` 分别提取映射的键和值,`POSITION` 用于对齐键和值的位置,从而确保键值对一一对应 [^3]。 ### 注意事项 - Impala 的 `UNNEST` 功能在某些版本中可能受到限制,建议使用较新的版本(如 Impala 3.0+)以获得更好的支持。 - 如果原始数据中存在 `NULL` 值,在 Impala 中需要手动处理,以避免丢失原始记录。可以通过 `LEFT JOIN UNNEST` 替代 `CROSS JOIN UNNEST` 来保留所有行 [^4]。 ### 示例代码 ```sql -- 处理数组类型 SELECT id, name, course FROM student CROSS JOIN UNNEST(courses) AS t(course); -- 处理映射类型 SELECT id, name, key, value FROM student CROSS JOIN UNNEST(MAP_KEYS(attributes)) AS k(key) CROSS JOIN UNNEST(MAP_VALUES(attributes)) AS v(value) WHERE POSITION = k.pos; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值