# 一、问题介绍
在使用 explode 进行炸列操作时,发现炸列后有的行消失了。
# 二、模拟场景
建表语句
drop table test.shyl_explode_test;
create table test.shyl_explode_test(
`id` string comment 'id',
`list` ARRAY<string> comment '列表'
)comment'测试炸列函数所使用的字段为空时,该行数据如何处理'
stored as orc;
插入数据
INSERT INTO TABLE shyl_explode_test VALUES
('1', array('A', 'B', 'C')),
('2', array('X', 'Y')),
('3', array(""))
('4', null)
('5', array(null));
当插入数据 (‘4’, null) 报错 [42000][40000] Error while compiling statement: FAILED: SemanticException 0:0 Expected 2 columns for insclause-0/test@shyl_explode_test; select produces 1 columns. Error encountered near token 'TOK_NULL'
大概的意思是说这个 list 字段的数据类型是 array,现在要插入一个 null 类型的,类型不匹配,
但是在实际情况中,表中数据类型为 array,其值为 null 的情况不少见,比如我们是通过上传文件到 hdfs,再通过 hive 建表关联数据,得到的表【具体过程没有验证,不确定是是否可以创建成功】;执行连接操作时,没有关联上的使用 null 填充【未验证】; 或者只插入一个列的值,【本文就采取这种方式】,得到 list 字段为空的情况:
INSERT INTO TABLE shyl_explode_test(id) VALUES ('4');
查看表中的数据
select * from test.shyl_explode_test;
| id | list |
|---|---|
| 1 | [“A”,“B”,“C”] |
| 2 | [“X”,“Y”] |
| 3 | [""] |
| 4 | null |
| 5 | [null] |
现根据list字段为null,查询出指定数据
select * from test.shyl_explode_test where list is null;
| id | list |
|---|
发现数据为空,原因可能与字段类型为 array 有关
现提供一个其它的方式查询
因为size(map/array)返回 -1 作为特殊的值,通常表示一个无效或异常的情况,而不是实际的大小或长度,所以利用它来查询空值
select size(null);
-1
select * from test.shyl_explode_test where size(list)=-1;
| id | list |
|---|---|
| 4 | null |
有关 sql 中的 null 参考此文:原文地址
# 三、执行 explode
select * from test.shyl_explode_test
lateral view explode(list)t1 as a;
| id | list | a |
|---|---|---|
| 1 | [“A”,“B”,“C”] | A |
| 1 | [“A”,“B”,“C”] | B |
| 1 | [“A”,“B”,“C”] | C |
| 2 | [“X”,“Y”] | X |
| 2 | [“X”,“Y”] | Y |
| 3 | [""] | |
| 5 | [null] | null |
我们发现 id 为 4 的那一行数据缺失,现在是有两列,当我的列数多,且其它列的数据重要时,会发生丢失一些重要数据的情况。
所以在执行 explode 的时候添加一些保护机制,附上一些不影响结果的默认值。
select * from test.shyl_explode_test
lateral view explode(nvl(list,array(NULL)))t1 as a;
| id | list | a |
|---|---|---|
| 1 | [“A”,“B”,“C”] | A |
| 1 | [“A”,“B”,“C”] | B |
| 1 | [“A”,“B”,“C”] | C |
| 2 | [“X”,“Y”] | X |
| 2 | [“X”,“Y”] | Y |
| 3 | [""] | |
| 4 | null | null |
| 5 | [null] | null |
# 四、explode+lateral view 源码剖析
【目前不会看源码】,之后有能力补上,从结果反推,像是炸列后执行的 inner join。