ToB企服应用市场:ToB评测及商务社交产业平台
标题:
【hive】lateral view侧视图
[打印本页]
作者:
东湖之滨
时间:
2024-8-14 22:09
标题:
【hive】lateral view侧视图
文档所在:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+LateralView
1.介绍
lateral view也叫侧视图,属于hive sql所特有的语法。用来实现类似标准sql中join的操纵。但区别在于:
join参与运算的每每是两个表,根据指定的关联字段举行横向连接。
lateral view参与运算的是一张表,这张表里每每存在某个多值的字段,通过侧视图结合UDTF函数可以将这个多值字段拆分为粒度更小的值,每一个拆分出来的值都会作为新的字段和一条原记录举行拼接。类似于列转行操纵,虽然严酷意义上不算列转行,因为只是增加了行数,但并未减少列数,只是减少了列中所包罗的字段个数。
2.语法
select
src.*,
tb_alias.col_alias
from src lateral view UDTF(src.col) tb_alias as col_alias [, col_alias, ...];
复制代码
以上只是一个基本的语法参考,tb_alias为表别名,这里的表指的是UDTF所返回的假造表。as col_alias [, col_alias, ...]是给这个假造表的字段指定别名,方便后续引用。返回的假造表中有几个字段,就得指定几个别名,业务中一样平常只返回一个。
关于字段别名,文档里说的是从hive 0.12.0字段别名可以省略,此时它继承自UDTF函数在定义时指定的字段名,但仅做了解即可,按照上面语法通用就不必要做一些非必要的改动。
重点是理解上述代码的逻辑实行过程
,UDTF会根据传入的字段先返回一张假造表,此时假造表的表名和字段名分别被命名为tb_alias 和col_alias,然后通过lateral view,将假造表的每条记录关联到原来所属的记录上去,类似于join操纵,只不过不必要我们显式指定on的字段,hive内部会自己识别原来属于哪条记录并关联。最后再从这张结果表中select我们必要的字段就可以了。
3.code demo
1)单重侧视图
with src as (
select '张三' as name, '唱;跳;rap'as skills
union all
select '李四' as name, '唱;跳'as skills
)
select
src.*,
tb.col_name
from src lateral view explode(split(skills,';')) tb as col_name;
复制代码
output:
2)多重侧视图
多重侧视图的实行过程是在上一步侧视图结果的基础上,再举行一次lateral view操纵,所以对于后面的lateral view,是可以直接引用前面lateral view结果表中的字段的。
下面通过代码对二重lateral view拆开分步演示,可以更好的理解实行逻辑。
step1:
with src as (
select '张三' as name, map('语文', '71;72;73', '数学', '81;82;83') as col
union all
select '李四' as name, map('语文', '90') as col
)
select src.*,
tb1.subject,
tb1.score
from src lateral view explode(col) tb1 as subject, score;
复制代码
output:
step2,基于step1的结果,对结果score列的值继承睁开:
with src as (
select '张三' as name, map('语文', '71;72;73', '数学', '81;82;83') as col
union all
select '李四' as name, map('语文', '90') as col
)
select src.*,
tb1.subject,
tb1.score,
tb2.score_detail
from src lateral view explode(col) tb1 as subject, score
lateral view explode(split(tb1.score, ';')) tb2 as score_detail;
复制代码
output:
固然,假如必要,可以继承lateral view下去。
3)lateral view outer
有一个点必要注意,就是实际任务中UDTF的返回结果可能存在空值null的情况,对于这种情况,hive会丢失原表中的数据行,因为本身lateral view就类似于join操纵,关联不上那就丢失了。
比方:
with src as (
select '张三' as name, '唱;跳;rap'as skills
union all
select '李四' as name, null as skills
)
select
src.*,
tb.col_name
from src lateral view explode(split(skills,';')) tb as col_name;
复制代码
output:
可以看到原始数据“李四”的信息就丢失了,同时必要注意这里的空值指的是null,而不是空字符串,这是两种不同的概念,好比下面这段sql:
with src as (
select '张三' as name, '唱;跳;rap'as skills
union all
select '李四' as name, '' as skills -- 这里修改null为空字符串''
)
select
src.*,
tb.col_name
from src lateral view explode(split(skills,';')) tb as col_name;
复制代码
output:
为了规避这种可能造成数据丢失的情况,hive从0.12.0版本及之后提供了lateral view outer来办理。这种方式可以理解为标准sql中的left join,纵然UDTF返回的结果为null,也会保留原表的这条数据。具体见代码:
with src as (
select '张三' as name, '唱;跳;rap'as skills
union all
select '李四' as name, null as skills
)
select
src.*,
tb.col_name
from src lateral view outer explode(split(skills,';')) tb as col_name;
复制代码
output:
4)tips(lateral view + json_tuple)
3)中当lateral view遇到explode爆炸函数返回null的时间原表记录也会丢失,但并非lateral view+返回null值的UDTF函数都会丢失原数据,比方json_tuple。
with t as (
select 1 as id, '{
"name": "小明",
"age": 18,
"score": {
"math": 100,
"english": 90
}
}' as json_str
)
select * from t
lateral view json_tuple(json_str, 'score') t1 as score
lateral view json_tuple(score, 'math1') t2 as math1;
复制代码
math1不存在,会以null的形式返回,不影响原数据,和explode处置惩罚null值时的方式不同。查了下原因:
这紧张是因为explode和json_tuple这两个函数的工作方式和目的不同。
explode函数的目的是将一行变成多行。比方,假如你有一行数据,此中一个列是一个数组,包罗三个元素,explode这个数组会天生三行,每行对应数组的一个元素。假如数组是空的或者null,那么explode就没有任何东西可以天生,所以结果集中不包罗这一行。
而json_tuple函数的目的是从JSON对象中提取值。假如JSON对象中不存在某个键,json_tuple只能返回NULL,因为它没有找到对应的值。但是,它并不会删除整行数据,因为你可能仍然从JSON对象中提取了其他的键和值。所以,纵然某个键在JSON对象中不存在,对应的行也会在结果集中保留,只不过对应的列值为NULL。
总的来说,explode函数是一个“天生”型的函数,它的目标是天生新的行,而json_tuple是一个“提取”型的函数,它的目标是提取现有的值。这就是为什么当它们遇到null或者不存在的值时,它们的举动会有所不同。
供理解参考。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4