解决 FAILED: UDFArgumentException explode() takes an array or a map as a parameter 并理解炸裂函数和侧视图


解决 FAILED: UDFArgumentException explode() takes an array or a map as a parameter 并理解炸裂函数和侧视图


一、解决 FAILED: UDFArgumentException explode() takes an array or a map as a parameter

1、背景

项目中数据处理后,进行查询得到的所有结果如下,其中 genre 字段类型,其实是一个字符串(业务逻辑处理后的结果),可视化展示,看着像一个数组而已

SELECT
    get_json_object(map_col,'$.game_name') game_name,
    get_json_object(map_col,'$.genre') genre
FROM
	ods_crawler_table                         
WHERE
	dt = '2023-02-26'       
	AND get_json_object(map_col,'$.code') = 'xxx'

2、接下来想要使用explode 函数,对genre 字段进行一行转成多行

SELECT
	explode(get_json_object(map_col,'$.genre')) genre 
FROM
	ods_crawler_table                          
WHERE
	dt = '2023-02-26'       
	AND get_json_object(map_col,'$.code') = 'xxx'	

3、报错

错误信息:FAILED: UDFArgumentException explode() takes an array or a map as a parameter

4、分析原因:

① 这个genre 只是表面看着是数组,其实它在业务处理后,实际上是一个String 类型
② 并且是一个带有多余的[]的String 类型的
③ 需要处理成数组类型,前提是先把多余的[] 去掉,然后,使用String的split 方法进行切割后返回的即是一个数组

split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ",")

------------------------------------------------------------------------------------------------------------------
SELECT
	split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ",") genre 
FROM
	ods_crawler_table                        
WHERE
	dt = '2023-02-26'       
	AND get_json_object(map_col,'$.code') = 'xxx'
结果如下:

再试试炸裂函数explode 效果:
SELECT
    explode(split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ","))  genre 
FROM
	ods_crawler_table                          
WHERE
	dt = '2023-02-26'       
AND get_json_object(map_col,'$.code') = 'xxx'

至此成功炸裂~~~~~~~~~~~~~

5、explode(genre) 和其他字段一起查询

  • 实际业务,字段game_name,genre 都要查询
SELECT
    get_json_object(map_col,'$.game_name') game_name,
    explode(split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ","))  genre 
FROM
	ods_crawler_table                           
WHERE
	dt = '2023-02-26'       
AND get_json_object(map_col,'$.code') = 'xxx'	
报错:
  • 报错信息:UDTF’s are not supported outside the SELECT clause, nor nested in expressions
分析:原因是因为这个字段genre,炸裂之后,转换成多列(3列),而game_name 字段依然是1列,列数不匹配
解决:侧视图(表)的聚合
ods_crawler_table -- 原先的表
LATERAL VIEW -- 聚合(本质上就是笛卡尔乘积)
explode(split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ",")) v -- 炸裂后作为一个表,两个表聚合之后成v表
as genre -- 是炸裂函数explode(split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ","))的别名


------------------------------------------------------------------------------------------------------------------------
SELECT
    get_json_object(map_col,'$.game_name') game_name,
    genre 
FROM
	ods_crawler_table      
LATERAL VIEW explode(split(regexp_replace(get_json_object(map_col,'$.genre'), '\\[|\\]', ''), ",")) v as genre		
WHERE
	dt = '2023-02-26'       
    AND get_json_object(map_col,'$.code') = 'xxx'
聚合效果:

小细节:lateral view+explode,一起使用后,有两个别名

  • 第一个别名是两个表聚合的别名,第二个别名是炸裂函数的别名

  • 语法

    tableA
    LATERAL VIEW -- 聚合
    explode(fieldB) v -- v 别名:tableA 和自身表使用了explode函数后得到的那个表,进行聚合后得到的新表
    as b -- b 别名:explode函数使用后起的别名
    



二、理解炸裂函数和侧视图

1、explode :

(1) 作用:一行数据转换成多列数据,用于array和map类型的数据。
(2) 语法和例子:
explode (array)
-- 炸裂字段array('A','B','C')
select explode(array('A','B','C')) as col;
col
A
B
C
explode (map)
-- 炸裂字段 map('A', 10, 'B',10, 'C',10)
select explode(map('A', 10, 'B',10, 'C',10)) as (key, value);
keyvalue
A10
B20
C30
posexplode (array)
select posexplode(array('A','B','C')) as (pos,val);
posval
0A
1B
2C
(3) 炸裂函数的不足:

炸裂某个字段之后,该字段和表其余字段的列数不匹配了,炸裂的字段不能和表的其他字段进行联合查询了。

解决:侧视图lateral view


2、lateral view

(1) 作用:结合UDTF一起使用,解决单独使用UDTF函数不能添加额外的select列的问题。

lateral view会将UDTF生成的结果放到一个虚拟表中,然后这个虚拟表会和输入行进行join来达到连接UDTF外的select字段的目的。

(2) 语法和例子:
□ 语法:
tableA
LATERAL VIEW -- 聚合
explode(fieldB) v -- v 别名:tableA 和自身表使用了explode函数后得到的那个表,进行聚合后得到的新表
as b -- b 别名:explode函数使用后起的别名
□ 例子:

原表格t查询结果如下:

select festival,good_name from tableA;
festivalgood_name
端午端阳,龙舟,重午
中秋团圆,祭月
春节新春,新岁,岁旦
-- 使用explode 函数
select explode(good_name) as good_name from tableA;
good_name
端阳
龙舟
重午
团圆
祭月
新春
新岁
岁旦
  • 想实现的效果:节日名称和别名聚合,在使用explode 函数的时候,直接和字段festival 一起查询 会报错

    select festival, explode(another_name) from tableA;
    
  • 报错 :UDTF’s are not supported outside the SELECT clause, nor nested in expressions,意思:explode(UDTF),不能直接和其他字段一起使用。

  • 解决 :使用 lateral view

    select festival, good_name 
    from tableA
    LATERAL VIEW explode(good_name) v 
    	as good_name;	
    
  • 效果:

festivalanother_name1
端午端阳
端午龙舟
端午重午
中秋团圆
中秋祭月
春节新春
春节新岁
春节岁旦





如果本文对你有帮助的话记得给一乐点个赞哦,感谢!

评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟庭大师兄

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值