Перейти к основному содержимому
Перейти к основному содержимому

Функция arrayJoin

Это очень необычная функция.

Обычные функции не изменяют набор строк, а только изменяют значения в каждой строке (отображение). Агрегатные функции сжимают набор строк (сводят или редуцируют). Функция arrayJoin берет каждую строку и генерирует набор строк (разворачивает).

Эта функция принимает массив в качестве аргумента и продублирует исходную строку на несколько строк в зависимости от количества элементов в массиве. Все значения в колонках просто копируются, за исключением значений в колонке, к которой применяется эта функция; она заменяется соответствующим значением массива.

Пример:

SELECT arrayJoin([1, 2, 3] AS src) AS dst, 'Hello', src
┌─dst─┬─\'Hello\'─┬─src─────┐
│   1 │ Hello     │ [1,2,3] │
│   2 │ Hello     │ [1,2,3] │
│   3 │ Hello     │ [1,2,3] │
└─────┴───────────┴─────────┘

Функция arrayJoin влияет на все части запроса, включая секцию WHERE. Обратите внимание на результат 2, даже несмотря на то, что подзапрос вернул 1 строку.

Пример:

SELECT sum(1) AS impressions
FROM
(
    SELECT ['Istanbul', 'Berlin', 'Bobruisk'] AS cities
)
WHERE arrayJoin(cities) IN ['Istanbul', 'Berlin'];
┌─impressions─┐
│           2 │
└─────────────┘

Запрос может использовать несколько функций arrayJoin. В этом случае трансформация выполняется несколько раз, и строки умножаются.

Пример:

SELECT
    sum(1) AS impressions,
    arrayJoin(cities) AS city,
    arrayJoin(browsers) AS browser
FROM
(
    SELECT
        ['Istanbul', 'Berlin', 'Bobruisk'] AS cities,
        ['Firefox', 'Chrome', 'Chrome'] AS browsers
)
GROUP BY
    2,
    3
┌─impressions─┬─city─────┬─browser─┐
│           2 │ Istanbul │ Chrome  │
│           1 │ Istanbul │ Firefox │
│           2 │ Berlin   │ Chrome  │
│           1 │ Berlin   │ Firefox │
│           2 │ Bobruisk │ Chrome  │
│           1 │ Bobruisk │ Firefox │
└─────────────┴──────────┴─────────┘

Важно!

Использование нескольких arrayJoin с одним и тем же выражением может не дать ожидаемых результатов из-за оптимизаций. В таких случаях рассмотрите возможность изменения повторяющегося выражения массива с помощью дополнительных операций, которые не повлияют на результат соединения - например, arrayJoin(arraySort(arr)), arrayJoin(arrayConcat(arr, []))

Пример:

SELECT
    arrayJoin(dice) as first_throw,
    /* arrayJoin(dice) as second_throw */ -- технически корректно, но приведет к уничтожению результирующего набора
    arrayJoin(arrayConcat(dice, [])) as second_throw -- намеренно изменено выражение, чтобы заставить пересчитывать
FROM (
    SELECT [1, 2, 3, 4, 5, 6] as dice
);

Обратите внимание на синтаксис ARRAY JOIN в запросе SELECT, который предлагает более широкие возможности. ARRAY JOIN позволяет вам одновременно преобразовать несколько массивов с одинаковым количеством элементов.

Пример:

SELECT
    sum(1) AS impressions,
    city,
    browser
FROM
(
    SELECT
        ['Istanbul', 'Berlin', 'Bobruisk'] AS cities,
        ['Firefox', 'Chrome', 'Chrome'] AS browsers
)
ARRAY JOIN
    cities AS city,
    browsers AS browser
GROUP BY
    2,
    3
┌─impressions─┬─city─────┬─browser─┐
│           1 │ Istanbul │ Firefox │
│           1 │ Berlin   │ Chrome  │
│           1 │ Bobruisk │ Chrome  │
└─────────────┴──────────┴─────────┘

Или вы можете использовать Tuple

Пример:

SELECT
    sum(1) AS impressions,
    (arrayJoin(arrayZip(cities, browsers)) AS t).1 AS city,
    t.2 AS browser
FROM
(
    SELECT
        ['Istanbul', 'Berlin', 'Bobruisk'] AS cities,
        ['Firefox', 'Chrome', 'Chrome'] AS browsers
)
GROUP BY
    2,
    3
┌─impressions─┬─city─────┬─browser─┐
│           1 │ Istanbul │ Firefox │
│           1 │ Berlin   │ Chrome  │
│           1 │ Bobruisk │ Chrome  │
└─────────────┴──────────┴─────────┘