解决 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);
key value
A 10
B 20
C 30

posexplode (array)

select posexplode(array('A','B','C')) as (pos,val);
pos val
0 A
1 B
2 C

(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;
festival good_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;
  • 效果:
festival another_name1
端午 端阳
端午 龙舟
端午 重午
中秋 团圆
中秋 祭月
春节 新春
春节 新岁
春节 岁旦




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

目录
相关文章
|
6月前
|
Python
使用array()函数创建数组
使用array()函数创建数组。
133 3
|
6月前
|
设计模式
ES6中新增Array.from()函数的用法详解
ES6中新增Array.from()函数的用法详解
75 1
|
6月前
Google Earth Engine(GEE)——从列表中少选所需要的数字不用map函数,还能如何实现?简单方法介绍
Google Earth Engine(GEE)——从列表中少选所需要的数字不用map函数,还能如何实现?简单方法介绍
45 0
|
5月前
|
Python
高阶函数如`map`, `filter`, `reduce`和`functools.partial`在Python中用于函数操作
【6月更文挑战第20天】高阶函数如`map`, `filter`, `reduce`和`functools.partial`在Python中用于函数操作。装饰器如`@timer`接收或返回函数,用于扩展功能,如记录执行时间。`timer`装饰器通过包裹函数并计算执行间隙展示时间消耗,如`my_function(2)`执行耗时2秒。
34 3
|
2月前
|
数据处理 Python
Pandas中的map函数应用
Pandas中的map函数应用
19 2
WK
|
2月前
|
Python
map函数
在Python中,`map()` 是一个内置的高阶函数,接受一个函数和一个或多个可迭代对象作为参数,将指定函数应用于每个元素,并返回包含应用结果的迭代器。若有多个可迭代对象,其元素会并行地传递给函数。`map()` 返回一个迭代器,需用 `list()` 转换。在Python 3中,`map()` 返回迭代器而非列表,并支持 `lambda` 表达式,适用于多种应用场景。注意,当输入的可迭代对象长度不同时,结果仅包含最短对象的长度。
WK
31 1
|
2月前
|
JavaScript 前端开发
JavaScript Array map() 方法
JavaScript Array map() 方法
|
3月前
|
JavaScript 前端开发 PHP
|
3月前
|
存储 关系型数据库 MySQL
|
5月前
|
存储 分布式计算 DataWorks
MaxCompute产品使用合集之要存储用户的下单所有产品,然后查询时要进行产品分组的,一般这种字段要使用ARRAY还是MAP
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。