Unnest 展开
示例
展开一个列表,生成 3 行(1、2、3):
SELECT unnest([1, 2, 3]);
展开一个结构体,生成两列(a、b):
SELECT unnest({'a': 42, 'b': 84});
递归展开结构体列表:
SELECT unnest([{'a': 42, 'b': 84}, {'a': 100, 'b': NULL}], recursive := true);
使用 max_depth 限制递归展开深度:
SELECT unnest([[[1, 2], [3, 4]], [[5, 6], [7, 8, 9], []], [[10, 11]]], max_depth := 2);
unnest 是一个特殊函数,用于将列表或结构体展开一层。它可作为普通标量函数使用,但仅限于 SELECT 子句。在调用 unnest 时传入 recursive 参数,可以展开多层列表和结构体。展开深度可通过 max_depth 参数限制(默认即按递归展开处理)。
展开列表
展开一个列表,生成 3 行(1、2、3):
SELECT unnest([1, 2, 3]);
展开一个列表,生成 3 行((1, 10)、(2, 10)、(3, 10)):
SELECT unnest([1, 2, 3]), 10;
展开两个长度不同的列表,生成 3 行((1, 10)、(2, 11)、(3, NULL)):
SELECT unnest([1, 2, 3]), unnest([10, 11]);
展开子查询中的列表列:
SELECT unnest(l) + 10 FROM (VALUES ([1, 2, 3]), ([4, 5])) tbl(l);
空结果:
SELECT unnest([]);
空结果:
SELECT unnest(NULL);
对列表使用 unnest 会为列表中的每个元素输出一行。同一 SELECT 子句中的常规标量表达式会在每一行重复。当在同一 SELECT 子句中展开多个列表时,会按并排方式展开;如果一个列表更长,较短列表将使用 NULL 补齐。
空列表和 NULL 列表都会展开为零行。
展开结构体
展开一个结构体,生成两列(a、b):
SELECT unnest({'a': 42, 'b': 84});
展开一个结构体,生成两列(a、b):
SELECT unnest({'a': 42, 'b': {'x': 84}});
对结构体使用 unnest 会为结构体中的每个字段输出一列。
递归展开
递归展开列表的列表,生成 5 行(1、2、3、4、5):
SELECT unnest([[1, 2, 3], [4, 5]], recursive := true);
递归展开结构体列表,生成两行两列(a、b):
SELECT unnest([{'a': 42, 'b': 84}, {'a': 100, 'b': NULL}], recursive := true);
展开一个结构体,生成两列(a、b):
SELECT unnest({'a': [1, 2, 3], 'b': 88}, recursive := true);
启用 recursive 调用 unnest 时,会先完整展开列表,再完整展开结构体。这对于完全扁平化“列表嵌套列表”或“结构体列表”这类列非常有用。注意:结构体内部的列表不会被展开。
设置展开最大深度
max_depth 参数可用于限制递归展开的最大深度(默认即按递归展开处理,无需单独指定)。
例如,将 max_depth 设为 2 时会得到:
SELECT unnest([[[1, 2], [3, 4]], [[5, 6], [7, 8, 9], []], [[10, 11]]], max_depth := 2) AS x;
| x |
|---|
| [1, 2] |
| [3, 4] |
| [5, 6] |
| [7, 8, 9] |
| [] |
| [10, 11] |
而将 max_depth 设为 3 时结果为:
SELECT unnest([[[1, 2], [3, 4]], [[5, 6], [7, 8, 9], []], [[10, 11]]], max_depth := 3) AS x;
| x |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
跟踪列表元素位置
若要跟踪每个元素在原始列表中的位置,可将 unnest 与 generate_subscripts 结合使用:
SELECT unnest(l) AS x, generate_subscripts(l, 1) AS index
FROM (VALUES ([1, 2, 3]), ([4, 5])) tbl(l);
| x | index |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 1 |
| 5 | 2 |