核心概念
explode(): 是一个 UDTF(User-Defined Table-Generating Function)。它接收一个数组或映射作为输入,并将其中的每个元素输出为一行。
它本身不能直接与表中的其他列一起查询。
LATERAL VIEW: 它的作用是将 UDTF(如 explode())生成的结果虚拟表与原始表的每一行进行关联(类似于侧向连接),
从而允许你在一个 SELECT 语句中同时查询原始列和爆炸后的列。
简单比喻:
想象你的原始表是一盒巧克力(每一行是一颗巧克力),有些巧克力里面包含多个果仁(数组)。explode() 就是把巧克力掰开,
取出每一颗果仁。LATERAL VIEW 的作用就是确保你能清楚地知道每一颗果仁是从哪一颗巧克力里取出来的。
语法
sql
SELECT
original_column1,
original_column2,
exploded_column
FROM original_table
LATERAL VIEW explode(complex_data_column) virtual_table_name AS exploded_column
complex_data_column : 要展开的数组或映射类型的列。
virtual_table_name : 为 explode() 生成的虚拟表指定一个别名(表名)。
exploded_column : 为 explode() 生成的虚拟表中的列指定一个别名(列名)。
示例详解
示例 1:展开数组(Array)
假设我们有一个 user_hobbies 表,记录了每个用户及其爱好(爱好以数组形式存储)。
user_id user_name hobbies
1 Alice ["hiking", "music"]
2 Bob ["reading", "game", "cooking"]
3 Charlie ["sports"]
我们想将每个爱好展开成单独的一行。
sql
SELECT
user_id,
user_name,
single_hobby
FROM user_hobbies
LATERAL VIEW explode(hobbies) hobbies_table AS single_hobby;
结果与解释:
user_id user_name single_hobby
1 Alice hiking
1 Alice music
2 Bob reading
2 Bob game
2 Bob cooking
3 Charlie sports
关键点:
原始表中 user_id=1 的一行(包含2个爱好),被展开成了两行。
原始表中 user_id=2 的一行(包含3个爱好),被展开成了三行。
原始表中的每一列(user_id, user_name)都与展开后的 single_hobby 正确关联。
示例 2:展开映射(Map)
假设我们有一个 product_scores 表,记录了产品来自不同平台的评分(评分以 Map 形式存储,key 是平台名,value 是分数)。
product_id product_name scores
101 iPhone {"AppStore":4.8, "Google":4.5, "Web":4.7}
102 Galaxy {"AppStore":4.6, "Web":4.4}
我们想将每个平台的评分展开成 平台 | 分数 这样的格式。
sql
SELECT
product_id,
product_name,
platform,
score
FROM product_scores
LATERAL VIEW explode(scores) scores_table AS platform, score;
结果与解释:
product_id product_name platform score
101 iPhone AppStore 4.8
101 iPhone Google 4.5
101 iPhone Web 4.7
102 Galaxy AppStore 4.6
102 Galaxy Web 4.4
关键点:
当 explode() 一个 Map 时,需要为虚拟表指定两个别名:一个用于接收 Key,一个用于接收 Value。
原始表中 product_id=101 的一行(包含3个键值对),被展开成了三行。
示例 3:处理空数组或 NULL - 使用 OUTER LATERAL VIEW
默认情况下,如果数组为 NULL 或空([]),explode() 不会生成任何行,导致原始表的这一行在结果中完全消失。
如果你希望保留这一行(即使没有可展开的元素),可以使用 OUTER LATERAL VIEW。
假设用户 David 没有爱好(空数组)。
user_id user_name hobbies
4 David []
sql
-- 使用 LATERAL VIEW (默认行为,David 会消失)
SELECT ... FROM user_hobbies
LATERAL VIEW explode(hobbies) h_tbl AS hobb;
-- 使用 OUTER LATERAL VIEW (David 会被保留,hobb 为 NULL)
SELECT ... FROM user_hobbies
OUTER LATERAL VIEW explode(hobbies) h_tbl AS hobb;
结果对比:
方式 user_id user_name single_hobby
LATERAL VIEW 1 Alice hiking
1 Alice music
... ... ...
(David 不在结果中)
OUTER LATERAL VIEW 1 Alice hiking
1 Alice music
... ... ...
4 David NULL
示例 4:同时展开多个数组
如果要展开的多个数组长度不一致,直接展开会产生笛卡尔积,这通常不是你想要的结果。更常见的做法是使用 posexplode()(带位置的展开)来确保对应关系。
假设有表 user_skills,包含技能和熟练度两个数组。
user_name skills proficiency
Alice ["SQL", "Java"] [90, 80]
sql
-- 错误做法:会产生 2 x 2 = 4 行,错误关联
SELECT
user_name,
skill,
prof
FROM user_skills
LATERAL VIEW explode(skills) s AS skill
LATERAL VIEW explode(proficiency) p AS prof;
-- 正确做法:使用 posexplode 按索引关联
SELECT
user_name,
skill,
prof
FROM user_skills
LATERAL VIEW posexplode(skills) s AS skill_idx, skill
LATERAL VIEW posexplode(proficiency) p AS prof_idx, prof
WHERE skill_idx = prof_idx;
总结与用途
特性 说明
主要用途 处理嵌套的复杂数据类型(Array, Map),将其"扁平化"为标准SQL表格式,以便进行关联、过滤、聚合等后续操作。
核心组件 LATERAL VIEW + explode() / posexplode() / 其他 UDTF
性能注意 爆炸操作可能会显著增加数据量(一行变多行),需谨慎使用。
应用场景 1. 用户标签分析:一个用户有多个标签,展开后分析标签分布。
2. 日志解析:一条日志包含多个事件ID或错误码,展开后进行统计。
3. 商品属性处理:一个商品有多个分类或多个价格(针对不同平台),展开后关联查询。
一句话总结:LATERAL VIEW explode() 是将 Hive 中"一行对多值"的列式存储,转换为标准SQL"一行一值"关系型表格的核心工具。
LATERAL VIEW EXPLODE 重要特性
最新推荐文章于 2025-12-02 21:20:38 发布
2415

被折叠的 条评论
为什么被折叠?



