前言:在对表数据进行批量处理过程中,常常碰上某个字段是一个array或者map形式的字段,一列数据的该字段信息同时存在多个值,当我们需要取出该数组中的每一个值实现一一对应关系的时候,可以考虑使用lateral view explode()/posexplode() 进行处理。

一、提要:explode()本身是Hive的自带函数,使用它可以将array或者map中的值逐行输出。

select explode(array('a','b','c','d','e'));

select explode(map('A','a','B','b','C','c'));

二、应用:lateral view explode()在工作环境中的使用。(lateral view用于和split、explode等UDTF一起使用的,能将一行数据拆分成多行数据,在此基础上可以对拆分的数据进行聚合,lateral view首先为原始表的每行调用UDTF,UDTF会把一行拆分成一行或者多行,lateral view在把结果组合,产生一个支持别名表的临时表。)

如下国家地区表dim_country,需要实现将shortname(array类型)中的国家简写逐个拆分出来实现与id及level的一一对应。

 如果只是用explode()会出现报错,因为explode()只能实现将shortname单字段进行炸开,一行变多行,但是id和level只有一行,故无法形成新表,这时候就需要用到lateral view。使用lateral view explode()可以将炸出的多行以临时表tmp的形式存在,其它的字段会进行相应的复制,实现与tmp的一一对应。

select id,level,country 
from dim_country
lateral view explode(shortname)tmp as country ;

(tips:即使数组中各元素相同,也都会一一列出)

 三、补充:split()函数的应用

如果需要lateral view explode()的字段类型是string,则需要用split()函数将之拆分成数组,然后再用lateral view explode()处理。同上dim_country表,如果shortname是string类型,则HQL如下,结果相同。

select id,level,country 
from dim_country
lateral view explode(split(shortname,’,’))tmp as country ;

正常数组类型两侧会带有[],但有些时候也可能是string类型,如果是string类型且两侧带有[],则需要先用substring()将两侧的[]去掉,可以考虑用如下方式:

SELECT regexp_replace(substr(shortname,2),substr(substr(shortname,2),-1,1),'');
或 
SELECT substr(shortname,2,length(shortname)-2);

&相关资料:试验过程的建表及插入SQL:

建表语句:
CREATE table dim_country (id bigint,level int,shortname ARRAY<string>);
插入语句(两种形式):
insert into table dim_country values (1,1,array('US','CA','UK'));
insert into dim_country(id,level,shortname) select 1,1,array('US','CA','AE');
insert into dim_country(id,level,shortname) select 1,1,array('US','US');

四、进阶:lateral view explode()在map类型上的使用问题及解决方法(lateral view posexplod() )。

        1、建表

CREATE table dim_map (id bigint,level int,shortname MAP<string,string>)
ROW FORMAT DELIMITED fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':';

        2、插入数据

insert into table dim_map 
values (1,1,str_to_map('yuwen:aaa,shuxue:bbb,yingyu:ccc,wuli:ddd,huaxue:eee'));

insert into dim_map(id,level,shortname) 
values (1,1,str_to_map('yuwen:100,shuxue:98,yingyu:88,wuli:89,huaxue:100'));

         3、explode()实现对map类型字段的炸开,形成key和value两段(但只能是map类型字段本身,不能另加别的字段)

SELECT explode(shortname) from dim_map;

         4、如果要加另外的字段,需要用到lateral view posexplod() 函数。

SELECT id,level,single_id,single_time from temp.dim_map
LATERAL VIEW posexplode(map_keys(shortname))t as single_id_index,single_id
LATERAL VIEW posexplode(map_values(shortname))t 
as single_time_index,single_time
where single_id_index = single_time_index;

posexplode()可以炸开一个数组,会形成两列,一列是自增序列,一列是炸出来的值。上诉方法则是通过自增序列实现一一对应结合。

 posexplode()可以通过与split(space(n))结合,可以实现插入固定的行数。

        5、补充:map_key()和map_value()可以直接对取出一个map中的所有key和所有value

SELECT id,level,map_keys(shortname), map_values(shortname) from temp.dim_map;

 五、使用lateral view注意事项:

1. lateral view使用在from后,where前,参照如下格式;

lateral view explode(数组字段)临时表名 as 别名 ;

2. from后可带多个lateral view;

3. 如果要拆分的字段有null值,需要使用lateral view outer 替代,避免数据缺失。

参考链接:

Hive SQL中的lateral view explode_IT农民工1的博客-CSDN博客

http://t.zoukankan.com/share23-p-10173311.html 

Hive-sql中的explode()函数和posexplode()函数_sql中explode_有语忆语的博客-CSDN博客

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐