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