LATERAL VIEW POSEXPLODE ~ Hive/Spark SQL

背景

LATERAL VIEW:侧视图,用来将数组 / Map 等集合字段炸开多行,实现一对多关联

posexplode():爆炸函数,和 explode 类似,但同时返回下标位置 + 元素值

LATERAL VIEW posexplode(数组字段) AS pos, val

作用:把数组拆成多行,额外带出每个元素在数组中的索引下标

explode vs posexplode 核心区别

explode(arr)

只输出数组里的元素,没有下标

sql 复制代码
explode(array('a','b','c')) AS val

结果:

复制代码
val
a
b
c

posexplode(arr)

输出两列:pos(下标,从 0 开始)、val(元素)

sql 复制代码
posexplode(array('a','b','c')) AS pos, val

结果:

复制代码
pos	val
0	a
1	b
2	c

LATERAL VIEW 作用

如果直接 select posexplode(col),只能单独查爆炸函数;

当需要同时查询原表普通字段 + 炸开后的多行数据,必须搭配 LATERAL VIEW

标准语法模板

sql 复制代码
SELECT 
    原表普通字段,
    pos,  -- 数组下标
    val   -- 数组元素
FROM 表名
LATERAL VIEW posexplode(数组字段) tmp AS pos, val;

tmp:侧视图别名(可省略,建议写上)

pos:自定义下标列名

val:自定义元素列名

实战示例

复制代码
id	 name	hobby_list
1	小明		["篮球","游戏"]
2	小红		["看书","画画","跑步"]
sql 复制代码
SELECT
    id,
    name,
    pos,
    hobby
FROM user_info
LATERAL VIEW posexplode(hobby_list) t AS pos, hobby;

输出结果

复制代码
id	name	pos	hobby
1	小明		0		篮球
1	小明		1		游戏
2	小红		0		看书
2	小红		1		画画
2	小红		2		跑步

常见使用场景

需要区分数组元素顺序

比如日志数组按时间有序,pos 代表第几条行为;

取数组第 N 个元素做过滤

sql 复制代码
-- 只保留数组第一个元素(pos=0)
WHERE pos = 0

有序数组转宽表

根据 pos 做行转列 collect_list + case when pos=x;

有序标签打分:下标越小权重越高,pos 参与计算。

关键特性 & 坑点

下标从 0 开始,不是 1

数组为 null / \[\] 空数组:整条行会消失(不生成任何行)

想保留空行用

sql 复制代码
LATERAL VIEW OUTER posexplode(...);

支持嵌套:多个 LATERAL VIEW 连续写,拆解多层数组;

Map 类型配套:posexplode(map) 会返回 pos, key, value 三列

OUTER 关键字补充(保留空数据)

不加 OUTER:数组为空则主表这条数据直接丢失

加 OUTER:数组为空时 pos=null, val=null,主表数据保留

sql 复制代码
LATERAL VIEW OUTER posexplode(hobby_list) t AS pos, hobby