文章目录
- [1. UDTF是什么](#1. UDTF是什么)
- [2. 典型函数explode](#2. 典型函数explode)
- [3. 案例实操](#3. 案例实操)
-
- [3.1 业务需求](#3.1 业务需求)
- [3.2 业务开发](#3.2 业务开发)
- [3.3 补充转义](#3.3 补充转义)
1. UDTF是什么
表生成函数
- 特点: 一进多出的函数
- 比如: explode(爆炸函数)
- 此类函数以后学习一个记住一个即可
2. 典型函数explode
explode函数接收map或者array类型的数据作为参数,然后把参数中的每个元素炸开变成一行数据。一个元素一行。这样的效果正好满足于输入一行输出多行。
explode(array)将array列表里的每个元素生成一行;
explode(map)将map里的每一对元素作为一行,其中key为一列,value为一列;
3. 案例实操
3.1 业务需求
我们已有数据如下
id | name |
---|---|
10 | CLARK|KING|MILLER |
20 | SMITH|JONES|SCOTT|ADAMS|FORD |
30 | ALLEN|WARD|MARTIN|BLAKE|TURNER|JAMES |
我们想要的结果
我们该如何实施?
3.2 业务开发
第一步: 在node1的/root/hivedata/下, 创建一个dept.txt文件, 添加以下数据:
shell
10 CLARK|KING|MILLER
20 SMITH|JONES|SCOTT|ADAMS|FORD
30 ALLEN|WARD|MARTIN|BLAKE|TURNER|JAMES
第二步: 在hive中创建表
sql
create database day04_hive;
use day04_hive;
create table day04_hive.dept(
dept_id int,
dept_name array<string>
)row format
delimited fields terminated by '\t'
collection items terminated by '|';
第三步: 导入数据到 dept表中
sql
load data local inpath '/root/hivedata/dept.txt' into table day04_hive.dept;
第四步: 测试是否加载成功
sql
select * from day04_hive.dept;
显示结果如下
shell
+---------------+----------------------------------------------------+
| dept.dept_id | dept.dept_name |
+---------------+----------------------------------------------------+
| 10 | ["CLARK","KING","MILLER"] |
| 20 | ["SMITH","JONES","SCOTT","ADAMS","FORD"] |
| 30 | ["ALLEN","WARD","MARTIN","BLAKE","TURNER","JAMES"] |
+---------------+----------------------------------------------------+
尝试使用explode:
sql
select explode(dept_name) from day04_hive.dept;
结果为:
shell
+---------+
| col |
+---------+
| CLARK |
| KING |
| MILLER |
| SMITH |
| JONES |
| SCOTT |
| ADAMS |
| FORD |
| ALLEN |
| WARD |
| MARTIN |
| BLAKE |
| TURNER |
| JAMES |
+---------+
接着尝试, 将 部门id加上:
sql
select dept_id,explode(dept_name) as dept_name from day04_hive.dept;
发现, 报错了:
shell
Error: Error while compiling statement: FAILED: SemanticException [Error 10081]: UDTF's are not supported outside the SELECT clause, nor nested in expressions (state=42000,code=10081)

UDTF函数特殊要求:
- 如果UDTF函数被使用在select后面, 不允许在出现其他的列或者字段
- UDTF函数不允许被其他的函数所嵌套, 但是他可以嵌套其他的函数
如何解决呢? 可以将这个结果作为临时表 ,然后和原有表进行关联即可
但是发现, 好像无法关联, 因为临时表和原有表没有关联条件, 此时如何办呢?
答: hive为了解决这种问题, 可以采用侧视图的方案, 而侧视图一般就是和UDTF配合使用, 解决UDTF函数特殊问题
侧视图: LATERAL VIEW
properties
用法:lateral view udtf(expression) tableAlias AS columnAlias
放置位置: 在SQL的最后面
接下来, 使用侧视图解决问题:
sql
select dept_id, name from day04_hive.dept lateral view explode(dept_name) t1 as name;
+----------+---------+
| dept_id | name |
+----------+---------+
| 10 | CLARK |
| 10 | KING |
| 10 | MILLER |
| 20 | SMITH |
| 20 | JONES |
| 20 | SCOTT |
| 20 | ADAMS |
| 20 | FORD |
| 30 | ALLEN |
| 30 | WARD |
| 30 | MARTIN |
| 30 | BLAKE |
| 30 | TURNER |
| 30 | JAMES |
+----------+---------+
思考: 如果刚刚建表的时候, 不使用array类型, 使用string类型, 如何解决呢?
sql
select dept_id, name from day04_hive.dept lateral view explode(split(dept_name,'|')) t1 as name;
同样的我们重复前面建表的操作再建立一个表,建表语句如下
sql
create table day04_hive.dept1(
dept_id int,
dept_name string
)row format delimited
fields terminated by '\t';
加载数据
shell
load data local inpath '/root/hivedata/dept.txt' into table day04_hive.dept1;
使用explode将其炸开
sql
select dept_id,t2.name from day04_hive.dept1 lateral view explode(split(dept_name,'|')) t2 as name;
结果如下,这是怎么回事?
这显然不是我们想要的,这是因为
split(dept_name,'|') 中的 | 在正则表达式中表示"或"操作,所以它会按照每个字符进行分割,导致:
"CLARK" 被分割成 ["C", "L", "A", "R", "K"]
"KING" 被分割成 ["K", "I", "N", "G"]
"MILLER" 被分割成 ["M", "I", "L", "L", "E", "R"]
然后 explode() 再对每个字母进行展开,就变成了一行一个字母。
这意味着我们需要转义符,使用双反斜杠转义(推荐)
sql
select dept_id,t2.name from day04_hive.dept1 lateral view explode(split(dept_name,'\\|')) t2 as name;

出现了我们想要的结果,大功告成。
3.3 补充转义
解决方案
您需要对 | 进行转义,有以下几种方法:
方法1:使用双反斜杠转义(推荐)
sql
SELECT explode(split(dept_name, '\\|')) FROM dept1;
方法2:使用方括号转义
sql
SELECT explode(split(dept_name, '[|]')) FROM dept1;
方法3:使用字符类转义
sql
SELECT explode(split(dept_name, '\\|')) FROM dept1;

如果有帮助到你,请点赞收藏