mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-10-18 14:30:49 +00:00
278 lines
11 KiB
Markdown
278 lines
11 KiB
Markdown
|
# Секция ARRAY JOIN {#select-array-join-clause}
|
|||
|
|
|||
|
Типовая операция для таблиц, содержащих столбец-массив — произвести новую таблицу, которая будет иметь столбец с каждым отдельным элементом массивов из изначального столбца, в то время как значения других столбцов дублируются. Это основной сценарий использования секции `ARRAY JOIN`.
|
|||
|
|
|||
|
Название этой секции происходит от того, что эту операцию можно рассматривать как исполняющий `JOIN` с массивом или вложенной структурой данных. Цель использования похожа на функцию [arrayJoin](../../functions/array-join.md#functions_arrayjoin), но функциональность секции шире.
|
|||
|
|
|||
|
Синтаксис:
|
|||
|
|
|||
|
``` sql
|
|||
|
SELECT <expr_list>
|
|||
|
FROM <left_subquery>
|
|||
|
[LEFT] ARRAY JOIN <array>
|
|||
|
[WHERE|PREWHERE <expr>]
|
|||
|
...
|
|||
|
```
|
|||
|
|
|||
|
Вы можете указать только одну секцию `ARRAY JOIN` в `SELECT` запросе.
|
|||
|
|
|||
|
Поддерживаемые виды `ARRAY JOIN` перечислены ниже:
|
|||
|
|
|||
|
- `ARRAY JOIN` - В базовом случае пустые массивы не включаются в результат.
|
|||
|
- `LEFT ARRAY JOIN` - Результат содержит строки с пустыми массивами. Значение для пустого массива устанавливается равным значению по умолчанию для типа элемента массива (обычно 0, пустая строка или NULL).
|
|||
|
|
|||
|
## Базовые примеры ARRAY JOIN {#basic-array-join-examples}
|
|||
|
|
|||
|
Приведенные ниже примеры демонстрируют использование `ARRAY JOIN` и `LEFT ARRAY JOIN`. Cоздадим таблицу с колонкой типа данных [Array](../../../sql-reference/data-types/array.md) и вставим в него значения:
|
|||
|
|
|||
|
``` 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 │ [] │
|
|||
|
└─────────────┴─────────┘
|
|||
|
```
|
|||
|
|
|||
|
В приведенном ниже примере используется секция `ARRAY JOIN`:
|
|||
|
|
|||
|
``` sql
|
|||
|
SELECT s, arr
|
|||
|
FROM arrays_test
|
|||
|
ARRAY JOIN arr;
|
|||
|
```
|
|||
|
|
|||
|
``` text
|
|||
|
┌─s─────┬─arr─┐
|
|||
|
│ Hello │ 1 │
|
|||
|
│ Hello │ 2 │
|
|||
|
│ World │ 3 │
|
|||
|
│ World │ 4 │
|
|||
|
│ World │ 5 │
|
|||
|
└───────┴─────┘
|
|||
|
```
|
|||
|
|
|||
|
В следующем примере используется `LEFT ARRAY JOIN`:
|
|||
|
|
|||
|
``` 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}
|
|||
|
|
|||
|
В секции `ARRAY JOIN` может быть указан алиас для массива. В этом случае элемент массива доступен по этому алиас, а сам массив доступен по исходному имени. Пример:
|
|||
|
|
|||
|
``` 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 │
|
|||
|
└───────┴─────────┴───┘
|
|||
|
```
|
|||
|
|
|||
|
Используя псевдонимы, вы можете выполнять `ARRAY JOIN` с внешними массивами. Например:
|
|||
|
|
|||
|
``` 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 │
|
|||
|
└─────────────┴──────────────┘
|
|||
|
```
|
|||
|
|
|||
|
Несколько массивов могут быть перечислены через запятую в секции `ARRAY JOIN`. В этом случае, `JOIN` выполняется с ними одновременно (прямая сумма, а не декартово произведение). Обратите внимание, что все массивы должны иметь одинаковый размер. Пример:
|
|||
|
|
|||
|
``` 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 │
|
|||
|
└───────┴─────────┴───┴─────┴────────┘
|
|||
|
```
|
|||
|
|
|||
|
В приведенном ниже примере используется функция [arrayEnumerate](../../../sql-reference/functions/array-functions.md#array_functions-arrayenumerate):
|
|||
|
|
|||
|
``` 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 со вложенной структурой данных {#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] │
|
|||
|
└───────┴────────┴────────────┘
|
|||
|
```
|
|||
|
|
|||
|
Алиас для вложенной структуры данных можно использовать, чтобы выбрать как результат JOIN-а, так и исходный массив. Пример:
|
|||
|
|
|||
|
``` 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] │
|
|||
|
└───────┴─────┴─────┴─────────┴────────────┘
|
|||
|
```
|
|||
|
|
|||
|
Пример использования функции [arrayEnumerate](../../../sql-reference/functions/array-functions.md#array_functions-arrayenumerate):
|
|||
|
|
|||
|
``` 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 │
|
|||
|
└───────┴─────┴─────┴─────────┴────────────┴─────┘
|
|||
|
```
|
|||
|
|
|||
|
## Детали реализации {#implementation-details}
|
|||
|
|
|||
|
Хотя секция `ARRAY JOIN` всегда должна быть указана перед [WHERE](where.md)/[PREWHERE](prewhere.md), технически они могут быть выполнены в любом порядке, если только результат `ARRAY JOIN` используется для фильтрации. Порядок обработки контролируется оптимизатором запросов.
|