UNNEST

更新时间:
复制 MD 格式

UNNEST 操作符用于将 ARRAY 类型字段展开为多行记录。根据数组元素类型不同,可分为展开普通数组和 STRUCT 数组两种场景。UNNEST 可独立使用,也可与 JOIN 语法组合,实现对表中数组列的横向展开。

UNNEST语法展开数组

UNNEST 操作符用于将 ARRAY 数组展开,返回一个表,每行对应数组中的一个元素。

命令格式

SELECT ... FROM UNNEST (<expression>) [AS <alias>];

参数说明

  • expression:必填。待展开的表达式。ARRAY 类型。

  • alias:可选。指定展开后列的别名。若省略,系统将自动生成默认列名(如 __generated_unnest_col_c0)。

使用示例

使用alias指定展开后列的别名。

SELECT * FROM unnest(array(1,2,3));

-- 返回结果
+---------------------------+
| __generated_unnest_col_c0 |
+---------------------------+
| 1                         |
| 2                         |
| 3                         |
+---------------------------+

SELECT * FROM unnest(array(1,2,3)) t;

-- 返回结果
+------+
| t    |
+------+
| 1    |
| 2    |
| 3    |
+------+

UNNEST语法展开STRUCT数组

UNNEST 操作符作用于 STRUCT 数组(数组中的每一个元素都是STRUCT类型)时,UNNEST 语法会展开 STRUCT 类型的每一个元素。若 STRUCT 中嵌套了其他 STRUCT 类型,则只能展开 STRUCT 的最上一层的元素,不会展开更深层次的元素。

命令格式

SELECT ... FROM UNNEST (<expression>) [AS <alias>];

参数说明

  • expression:必填。待展开的表达式。STRUCT 数组,即 ARRAY<STRUCT> 类型。

  • alias:可选。指定展开后 STRUCT 列的别名。可通过 <alias>.field 引用字段,也可直接使用字段名。

使用示例

示例 1:使用 alias 指定展开后 STRUCT 元素的别名

SELECT * FROM UNNEST(ARRAY(STRUCT(1 AS a, 2 AS b), STRUCT(3 AS a, 4 AS b)));

-- 返回结果
+------+------+
| a    | b    |
+------+------+
| 1    | 2    |
| 3    | 4    |
+------+------+

SELECT *, t FROM UNNEST(ARRAY(STRUCT(1 AS a, 2 AS b), STRUCT(3 AS a, 4 AS b))) t;

-- 返回结果
+------+------+------------+
| a    | b    | t          |
+------+------+------------+
| 1    | 2    | {a:1, b:2} |
| 3    | 4    | {a:3, b:4} |
+------+------+------------+

示例 2:通过设置的别名来访问里面的元素,也可以通过 <alias>.field 访问STRUCT的元素。

SELECT a, t.a FROM UNNEST(ARRAY(STRUCT(1 AS a, 2 AS b), STRUCT(3 AS a, 4 AS b))) t;

-- 返回结果
+------+------+
| a    | a_1  |
+------+------+
| 1    | 1    |
| 3    | 3    |
+------+------+

示例 3:UNNEST 语法只能展开 STRUCT 的最上一层的元素,不会展开更深层次的元素。比如对于 STRUCT 内部还有一个 STRUCT 类型的值,并不会把内层的 STRUCT 展开。

SELECT * FROM UNNEST(ARRAY(STRUCT(STRUCT(1 AS a1, 2 AS a2) AS a, 3 AS b), STRUCT(STRUCT(4 AS a1, 5 AS a2) AS a, 6 AS b))) t;

-- 返回结果
+--------------+------+
| a            | b    |
+--------------+------+
| {a1:1, a2:2} | 3    |
| {a1:4, a2:5} | 6    |
+--------------+------+

UNNEST语法在JOIN语法的使用方法

UNNEST 语法和 JOIN 语法同样作为 FROM 语法的子句,可以组合使用。当 UNNEST 语法作为 JOIN 语法的右表时,UNNEST 语法可以指定 JOIN 语法左表的某一列(ARRAY类型)进行展开。

命令格式

SELECT ... FROM ... JOIN UNNEST (<expression>) [AS <alias>] [ON <join_condition>]

参数说明

  • expression:必填。JOIN 左表中 ARRAY 类型的列。

  • alias:可选。指定展开后的元素的别名。

  • join_condition:可选。JOIN 连接条件,是一个或多个等式表达式组合。格式为on equality_expression [and equality_expression]...,equality_expression为等式表达式。

使用示例

示例 1:UNNEST 指定的 JOIN 左表的列必须是 ARRAY 类型,可以通过设置 alias 来指代 ARRAY 类型的每一个元素。

WITH t AS (SELECT * FROM VALUES (ARRAY(1,2,3)) t(a))
SELECT * FROM t JOIN UNNEST(t.a);

-- 返回结果
+-----------+---------------------------+
| a         | __generated_unnest_col_c0 |
+-----------+---------------------------+
| [1, 2, 3] | 1                         |
| [1, 2, 3] | 2                         |
| [1, 2, 3] | 3                         |
+-----------+---------------------------+

WITH t AS (SELECT * FROM VALUES (ARRAY(1,2,3)) t(a))
SELECT * FROM t JOIN UNNEST(t.a) col;

-- 返回结果
+-----------+------+
| a         | col  |
+-----------+------+
| [1, 2, 3] | 1    |
| [1, 2, 3] | 2    |
| [1, 2, 3] | 3    |
+-----------+------+

示例 2:UNNEST 指定的 JOIN 左表的列,其 ARRAY 内部的元素类型也可以是 STRUCT 类型,此时 UNNEST 语法会展开 STRUCT 中的每一个字段。

WITH t AS (SELECT * FROM VALUES (ARRAY(STRUCT(1 AS f1, 2 AS f2), STRUCT(3 AS f1, 4 AS f2))) t(a))
SELECT * FROM t JOIN UNNEST(t.a);

-- 返回结果
+------------------------------+------+------+
| a                            | f1   | f2   |
+------------------------------+------+------+
| [{f1:1, f2:2}, {f1:3, f2:4}] | 1    | 2    |
| [{f1:1, f2:2}, {f1:3, f2:4}] | 3    | 4    |
+------------------------------+------+------+

WITH t AS (SELECT * FROM VALUES (ARRAY(STRUCT(1 AS f1, 2 AS f2), STRUCT(3 AS f1, 4 AS f2))) t(a))
SELECT *, col.f1 FROM t JOIN UNNEST(t.a) col;

-- 返回结果
+------------------------------+------+------+------+
| a                            | f1   | f2   | f1_1 |
+------------------------------+------+------+------+
| [{f1:1, f2:2}, {f1:3, f2:4}] | 1    | 2    | 1    |
| [{f1:1, f2:2}, {f1:3, f2:4}] | 3    | 4    | 3    |
+------------------------------+------+------+------+

示例 3:使用 ON 等值条件进行过滤

WITH user_configs AS (
  SELECT 
    'user_001' AS user_id,
    2 AS current_dept_id,
    ARRAY(1, 2, 3) AS allowed_dept_ids
  UNION ALL
  SELECT 
    'user_002' AS user_id,
    4 AS current_dept_id,
    ARRAY(4, 5) AS allowed_dept_ids
)

SELECT 
  u.user_id,
  u.current_dept_id,
  dept_id AS allowed_dept_id
FROM user_configs u
JOIN UNNEST(u.allowed_dept_ids) AS dept_id 
  ON dept_id = u.current_dept_id;

-- 返回结果
+----------+-----------------+-----------------+
| user_id  | current_dept_id | allowed_dept_id |
+----------+-----------------+-----------------+
| user_001 | 2               | 2               |
| user_002 | 4               | 4               |
+----------+-----------------+-----------------+