跳到主要内容

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

跟踪列表元素位置

若要跟踪每个元素在原始列表中的位置,可将 unnestgenerate_subscripts 结合使用:

SELECT unnest(l) AS x, generate_subscripts(l, 1) AS index
FROM (VALUES ([1, 2, 3]), ([4, 5])) tbl(l);
xindex
11
22
33
41
52