- content
说明
unnest 和 unwind 都是列转行命令,用于将数组或 Map 类型的字段拆分成多行,其余字段复制到每一行。
| 命令 | 语法风格 | 来源 |
|---|---|---|
unwind |
unwind(字段1, 字段2, ...) |
类似 MongoDB 的 unwind |
unnest |
UNNEST(字段) as t(字段1, 字段2) |
类似 Flink/PG 的 unnest |
两者的核心区别:
unwind可以同时拆分多个字段,做笛卡尔积。unnest一次拆分一个字段,但可以自定义输出列名。
unwind 语法
select unwind(字段1, 字段2, ...) from ...
-- 或作为后置命令
select ...; unwind(字段1, 字段2, ...)
拆分数组
-- 把 b 字段(数组)拆成两行,a 字段复制到每一行
select * from [{'a':1, 'b':['b1','b2']}];
-- 结果:[{a:1, b:'b1'}, {a:1, b:'b2'}]
-- 也可以在 select 中直接用 unwind
select unwind(b) b from [{'a':1, 'b':['b1','b2']}];
-- 结果:[{a:1, b:'b1'}, {a:1, b:'b2'}]
多字段拆分(笛卡尔积)
-- 同时拆分 b 和 c,做笛卡尔积
select * from [{'a':1, 'b':['b1','b2'], 'c':['c1','c2','c3']}];
unwind(b, c);
-- 结果:6 行(2×3 笛卡尔积)
-- [{a:1,b:'b1',c:'c1'}, {a:1,b:'b1',c:'c2'}, {a:1,b:'b1',c:'c3'},
-- {a:1,b:'b2',c:'c1'}, {a:1,b:'b2',c:'c2'}, {a:1,b:'b2',c:'c3'}]
拆分逗号分隔字符串
-- 用 toList 把字符串转成数组再 unwind
select unwind(toList(b)) b from [{'a':1, 'b':'b1,b2'}];
-- 结果:[{a:1, b:'b1'}, {a:1, b:'b2'}]
拆分 Map
-- 把 Map 拆成 key/value 两列
select * from [{'a':1, 'b':{'x':1, 'y':2}}];
unwind(b);
-- 结果:[{a:1, b_key:'x', b_value:1}, {a:1, b_key:'y', b_value:2}]
unnest 语法
select ... from UNNEST(字段) as t(列名1, 列名2)
字段:要拆分的 Map 或数组字段名(可用反引号包裹)。t:别名(可省略)。列名1, 列名2:拆分后的输出列名。- 拆 Map 时:第一个列名对应 key,第二个对应 value。
- 拆数组时:第一个列名对应数组元素。
例子
-- 拆分 Map,输出 mapKey 和 mapValue 两列
select * from UNNEST(pageInfo) as t(mapKey, mapValue);
-- 格式化后:unnest(pageInfo) as t(`mapKey` AS mapKey, `mapValue` AS mapValue)
-- 不加反引号也可以
select * from UNNEST(pageInfo) as t(mapKey, mapValue);
-- 格式化后:unnest(pageInfo) as t(mapKey, mapValue)
注意事项
unwind可以同时拆多个字段做笛卡尔积,unnest一次只拆一个。unwind拆 Map 时输出列名固定为字段_key和字段_value;unnest可以自定义列名。unwind可以在 select 字段列表中使用(select unwind(b) b),也可以作为后置命令。- 如果字段不是数组/Map,
unwind会先用toList尝试转换(如把逗号字符串转数组)。