首页 / 数组和 Map
EXPLODE 数组展开为多行
EXPLODE 把数组的每个元素展开成一行,常用于处理多值字段。MaxCompute、Doris、Hive 和 Spark 用 EXPLODE,Hologres 和 StarRocks 用 UNNEST,Flink 用 CROSS JOIN UNNEST。空数组和 NULL 数组的处理是迁移时最容易漏掉的地方。
各引擎写法
| 引擎 | 支持 | 写法 | 说明 | 依据 |
|---|---|---|---|---|
| MaxCompute | 支持 | EXPLODE(var) |
支持 array 和 map。同一个 SELECT 只能有一个 EXPLODE,也不能同时选其他列,不能与 GROUP BY 等一起使用。数组为 NULL 时不输出行。 | 官方文档 |
| Hologres | 需改写 | UNNEST(anyarray) |
把数组的每个元素展开成一行。 | 官方文档 |
| StarRocks | 需改写 | FROM t, UNNEST(arr) AS u(x) |
UNNEST 是表函数,配合横向连接使用,不需要写 LATERAL。NULL 或空数组不输出行;3.2.7 起可以用 LEFT JOIN ... ON TRUE 保留这些行。 | 官方文档 |
| Doris | 支持 | LATERAL VIEW EXPLODE(arr) t AS x |
通常配合 LATERAL VIEW 使用。EXPLODE 对空数组和 NULL 不输出行,EXPLODE_OUTER 会保留一行 NULL。 | 官方文档 |
| Hive | 支持 | explode(array | map) |
UDTF,数组展开为一列 col,map 展开为 key 和 value 两列。需要元素位置时用 posexplode,位置从 0 开始。 | 官方文档 |
| Spark SQL | 支持 | explode(expr) |
Spark 1.0.0 起提供。数组默认列名为 col,map 为 key 和 value。需要保留空数组的行时用 explode_outer。 | 官方文档 |
| Flink SQL | 需改写 | CROSS JOIN UNNEST(arr) AS t(x) |
内置函数中没有 EXPLODE,数组展开写在 JOIN 中:CROSS JOIN UNNEST,也支持 LEFT JOIN。需要元素位置时加 WITH ORDINALITY,位置从 1 开始,目前只支持 CROSS JOIN。也可以展开 map 和 multiset。 | 官方文档 |
迁移注意事项
- 空数组和 NULL 数组的行会被直接丢掉:MaxCompute、Doris 的 EXPLODE 和 StarRocks 的 UNNEST 都是这样。需要保留时,Doris 和 Spark 用 EXPLODE_OUTER,StarRocks 3.2.7 起用 LEFT JOIN UNNEST(...) ON TRUE。
- MaxCompute 的 EXPLODE 不能和其他列写在同一个 SELECT 里。需要同时取其他列时,要改成 LATERAL VIEW 写法。
- 数组里的 NULL 元素会作为一行 NULL 输出,展开后如果要过滤,记得加 WHERE x IS NOT NULL。
- 需要元素位置时,Hive 和 Spark 的 posexplode 位置从 0 开始,Flink 的 WITH ORDINALITY 从 1 开始,迁移时要调整下标。
示例
把商品的标签数组展开成多行
SELECT item_id, tag FROM items LATERAL VIEW EXPLODE(tags) t AS tag;SELECT item_id, UNNEST(tags) AS tag FROM items;SELECT item_id, u.tag FROM items, UNNEST(tags) AS u(tag);SELECT item_id, tag FROM items LATERAL VIEW EXPLODE(tags) t AS tag;SELECT item_id, explode(tags) AS tag FROM items;SELECT item_id, t.tag FROM items CROSS JOIN UNNEST(tags) AS t(tag);