slug: /zh/sql-reference/statements/select/array-join
sidebar_label: ARRAY JOIN
ARRAY JOIN子句 {#select-array-join-clause}
对于包含数组列的表来说是一种常见的操作,用于生成一个新表,该表具有包含该初始列中的每个单独数组元素的列,而其他列的值将被重复显示。 这是 ARRAY JOIN 语句最基本的场景。
它可以被视为执行 JOIN 并具有数组或嵌套数据结构。 类似于 arrayJoin 功能,但该子句功能更广泛。
语法:
SELECT <expr_list>FROM <left_subquery>[LEFT] ARRAY JOIN <array>[WHERE|PREWHERE <expr>]...
您只能在 SELECT 查询指定一个 ARRAY JOIN 。
ARRAY JOIN 支持的类型有:
ARRAY JOIN- 一般情况下,空数组不包括在结果中JOIN.LEFT ARRAY JOIN- 的结果JOIN包含具有空数组的行。 空数组的值设置为数组元素类型的默认值(通常为0、空字符串或NULL)。
基本 ARRAY JOIN 示例 {#basic-array-join-examples}
下面的例子展示 ARRAY JOIN 和 LEFT ARRAY JOIN 的用法,让我们创建一个表包含一个 Array 的列并插入值:
CREATE TABLE arrays_test(s String,arr Array(UInt8)) ENGINE = Memory;INSERT INTO arrays_testVALUES ('Hello', [1,2]), ('World', [3,4,5]), ('Goodbye', []);
┌─s───────────┬─arr─────┐│ Hello │ [1,2] ││ World │ [3,4,5] ││ Goodbye │ [] │└─────────────┴─────────┘
下面的例子使用 ARRAY JOIN 子句:
SELECT s, arrFROM arrays_testARRAY JOIN arr;
┌─s─────┬─arr─┐│ Hello │ 1 ││ Hello │ 2 ││ World │ 3 ││ World │ 4 ││ World │ 5 │└───────┴─────┘
下一个示例使用 LEFT ARRAY JOIN 子句:
SELECT s, arrFROM arrays_testLEFT ARRAY JOIN arr;
┌─s───────────┬─arr─┐│ Hello │ 1 ││ Hello │ 2 ││ World │ 3 ││ World │ 4 ││ World │ 5 ││ Goodbye │ 0 │└─────────────┴─────┘
使用别名 {#using-aliases}
在使用ARRAY JOIN 时可以为数组指定别名,数组元素可以通过此别名访问,但数组本身则通过原始名称访问。 示例:
SELECT s, arr, aFROM arrays_testARRAY JOIN arr AS a;
┌─s─────┬─arr─────┬─a─┐│ Hello │ [1,2] │ 1 ││ Hello │ [1,2] │ 2 ││ World │ [3,4,5] │ 3 ││ World │ [3,4,5] │ 4 ││ World │ [3,4,5] │ 5 │└───────┴─────────┴───┘
可以使用别名与外部数组执行 ARRAY JOIN 。 例如:
SELECT s, arr_externalFROM arrays_testARRAY JOIN [1, 2, 3] AS arr_external;
┌─s───────────┬─arr_external─┐│ Hello │ 1 ││ Hello │ 2 ││ Hello │ 3 ││ World │ 1 ││ World │ 2 ││ World │ 3 ││ Goodbye │ 1 ││ Goodbye │ 2 ││ Goodbye │ 3 │└─────────────┴──────────────┘
在 ARRAY JOIN 中,多个数组可以用逗号分隔, 在这例子中 JOIN 与它们同时执行(直接sum,而不是笛卡尔积)。 请注意,所有数组必须具有相同的大小。 示例:
SELECT s, arr, a, num, mappedFROM arrays_testARRAY JOIN arr AS a, arrayEnumerate(arr) AS num, arrayMap(x -> x + 1, arr) AS mapped;
┌─s─────┬─arr─────┬─a─┬─num─┬─mapped─┐│ Hello │ [1,2] │ 1 │ 1 │ 2 ││ Hello │ [1,2] │ 2 │ 2 │ 3 ││ World │ [3,4,5] │ 3 │ 1 │ 4 ││ World │ [3,4,5] │ 4 │ 2 │ 5 ││ World │ [3,4,5] │ 5 │ 3 │ 6 │└───────┴─────────┴───┴─────┴────────┘
下面的例子使用 arrayEnumerate 功能:
SELECT s, arr, a, num, arrayEnumerate(arr)FROM arrays_testARRAY JOIN arr AS a, arrayEnumerate(arr) AS num;
┌─s─────┬─arr─────┬─a─┬─num─┬─arrayEnumerate(arr)─┐│ Hello │ [1,2] │ 1 │ 1 │ [1,2] ││ Hello │ [1,2] │ 2 │ 2 │ [1,2] ││ World │ [3,4,5] │ 3 │ 1 │ [1,2,3] ││ World │ [3,4,5] │ 4 │ 2 │ [1,2,3] ││ World │ [3,4,5] │ 5 │ 3 │ [1,2,3] │└───────┴─────────┴───┴─────┴─────────────────────┘
具有嵌套数据结构的数组连接 {#array-join-with-nested-data-structure}
ARRAY JOIN 也适用于 嵌套数据结构:
CREATE TABLE nested_test(s String,nest Nested(x UInt8,y UInt32)) ENGINE = Memory;INSERT INTO nested_testVALUES ('Hello', [1,2], [10,20]), ('World', [3,4,5], [30,40,50]), ('Goodbye', [], []);
┌─s───────┬─nest.x──┬─nest.y─────┐│ Hello │ [1,2] │ [10,20] ││ World │ [3,4,5] │ [30,40,50] ││ Goodbye │ [] │ [] │└─────────┴─────────┴────────────┘
SELECT s, `nest.x`, `nest.y`FROM nested_testARRAY JOIN nest;
┌─s─────┬─nest.x─┬─nest.y─┐│ Hello │ 1 │ 10 ││ Hello │ 2 │ 20 ││ World │ 3 │ 30 ││ World │ 4 │ 40 ││ World │ 5 │ 50 │└───────┴────────┴────────┘
当指定嵌套数据结构的名称 ARRAY JOIN,意思是一样的 ARRAY JOIN 它包含的所有数组元素。 下面列出了示例:
SELECT s, `nest.x`, `nest.y`FROM nested_testARRAY JOIN `nest.x`, `nest.y`;
┌─s─────┬─nest.x─┬─nest.y─┐│ Hello │ 1 │ 10 ││ Hello │ 2 │ 20 ││ World │ 3 │ 30 ││ World │ 4 │ 40 ││ World │ 5 │ 50 │└───────┴────────┴────────┘
这种变化也是有道理的:
SELECT s, `nest.x`, `nest.y`FROM nested_testARRAY JOIN `nest.x`;
┌─s─────┬─nest.x─┬─nest.y─────┐│ Hello │ 1 │ [10,20] ││ Hello │ 2 │ [10,20] ││ World │ 3 │ [30,40,50] ││ World │ 4 │ [30,40,50] ││ World │ 5 │ [30,40,50] │└───────┴────────┴────────────┘
可以将别名用于嵌套数据结构,以便选择 JOIN 结果或源数组。 例如:
SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`FROM nested_testARRAY JOIN nest AS n;
┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┐│ Hello │ 1 │ 10 │ [1,2] │ [10,20] ││ Hello │ 2 │ 20 │ [1,2] │ [10,20] ││ World │ 3 │ 30 │ [3,4,5] │ [30,40,50] ││ World │ 4 │ 40 │ [3,4,5] │ [30,40,50] ││ World │ 5 │ 50 │ [3,4,5] │ [30,40,50] │└───────┴─────┴─────┴─────────┴────────────┘
使用功能 arrayEnumerate 的例子:
SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`, numFROM nested_testARRAY JOIN nest AS n, arrayEnumerate(`nest.x`) AS num;
┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┬─num─┐│ Hello │ 1 │ 10 │ [1,2] │ [10,20] │ 1 ││ Hello │ 2 │ 20 │ [1,2] │ [10,20] │ 2 ││ World │ 3 │ 30 │ [3,4,5] │ [30,40,50] │ 1 ││ World │ 4 │ 40 │ [3,4,5] │ [30,40,50] │ 2 ││ World │ 5 │ 50 │ [3,4,5] │ [30,40,50] │ 3 │└───────┴─────┴─────┴─────────┴────────────┴─────┘
实现细节 {#implementation-details}
运行时优化查询执行顺序 ARRAY JOIN. 虽然 ARRAY JOIN 必须始终之前指定 WHERE/PREWHERE 子句中的查询,从技术上讲,它们可以以任何顺序执行,除非结果 ARRAY JOIN 用于过滤。 处理顺序由查询优化器控制。
