ClickHouse/docs/ru/query_language/functions/array_functions.md
Denis Zhuravlev 3f40cd7eef
Update array_functions.md
added note about ArrayElement index 0 case.
2019-09-05 19:33:36 -03:00

29 KiB
Raw Blame History

Функции по работе с массивами

empty

Возвращает 1 для пустого массива, и 0 для непустого массива. Тип результата - UInt8. Функция также работает для строк.

notEmpty

Возвращает 0 для пустого массива, и 1 для непустого массива. Тип результата - UInt8. Функция также работает для строк.

length

Возвращает количество элементов в массиве. Тип результата - UInt64. Функция также работает для строк.

emptyArrayUInt8, emptyArrayUInt16, emptyArrayUInt32, emptyArrayUInt64

emptyArrayInt8, emptyArrayInt16, emptyArrayInt32, emptyArrayInt64

emptyArrayFloat32, emptyArrayFloat64

emptyArrayDate, emptyArrayDateTime

emptyArrayString

Принимает ноль аргументов и возвращает пустой массив соответствующего типа.

emptyArrayToSingle

Принимает пустой массив и возвращает массив из одного элемента, равного значению по умолчанию.

range(N)

Возвращает массив чисел от 0 до N-1. На всякий случай, если на блок данных, создаются массивы суммарной длины больше 100 000 000 элементов, то кидается исключение.

array(x1, ...), оператор [x1, ...]

Создаёт массив из аргументов функции. Аргументы должны быть константами и иметь типы, для которых есть наименьший общий тип. Должен быть передан хотя бы один аргумент, так как иначе непонятно, какого типа создавать массив. То есть, с помощью этой функции невозможно создать пустой массив (для этого используйте функции emptyArray*, описанные выше). Возвращает результат типа Array(T), где T - наименьший общий тип от переданных аргументов.

arrayConcat

Объединяет массивы, переданные в качестве аргументов.

arrayConcat(arrays)

Параметры

  • arrays произвольное количество элементов типа Array Пример
SELECT arrayConcat([1, 2], [3, 4], [5, 6]) AS res
┌─res───────────┐
│ [1,2,3,4,5,6] │
└───────────────┘

arrayElement(arr, n), operator arr[n]

Достаёт элемент с индексом n из массива arr. n должен быть любым целочисленным типом. Индексы в массиве начинаются с единицы. Поддерживаются отрицательные индексы. В этом случае, будет выбран соответствующий по номеру элемент с конца. Например, arr[-1] - последний элемент массива.

Если индекс выходит за границы массива, то возвращается некоторое значение по умолчанию (0 для чисел, пустая строка для строк и т. п.), кроме случая с неконстантным массивом и константным индексом 0 (в этом случае будет ошибка Array indices are 1-based).

has(arr, elem)

Проверяет наличие элемента elem в массиве arr. Возвращает 0, если элемента в массиве нет, или 1, если есть.

NULL обрабатывается как значение.

SELECT has([1, 2, NULL], NULL)

┌─has([1, 2, NULL], NULL)─┐
│                       1 │
└─────────────────────────┘

hasAll

Проверяет, является ли один массив подмножеством другого.

hasAll(set, subset)

Параметры

  • set массив любого типа с набором элементов.
  • subset массив любого типа со значениями, которые проверяются на вхождение в set.

Возвращаемые значения

  • 1, если set содержит все элементы из subset.
  • 0, в противном случае.

Особенности

  • Пустой массив является подмножеством любого массива.
  • NULL обрабатывается как значение.
  • Порядок значений в обоих массивах не имеет значения.

Примеры

SELECT hasAll([], []) возвращает 1.

SELECT hasAll([1, Null], [Null]) возвращает 1.

SELECT hasAll([1.0, 2, 3, 4], [1, 3]) возвращает 1.

SELECT hasAll(['a', 'b'], ['a']) возвращает 1.

SELECT hasAll([1], ['a']) возвращает 0.

SELECT hasAll([[1, 2], [3, 4]], [[1, 2], [3, 5]]) возвращает 0.

hasAny

Проверяет, имеют ли два массива хотя бы один общий элемент.

hasAny(array1, array2)

Параметры

  • array1 массив любого типа с набором элементов.
  • array2 массив любого типа с набором элементов.

Возвращаемые значения

  • 1, если array1 и array2 имеют хотя бы один одинаковый элемент.
  • 0, в противном случае.

Особенности

  • NULL обрабатывается как значение.
  • Порядок значений в обоих массивах не имеет значения.

Примеры

SELECT hasAny([1], []) возвращает 0.

SELECT hasAny([Null], [Null, 1]) возвращает 1.

SELECT hasAny([-128, 1., 512], [1]) возвращает 1.

SELECT hasAny([[1, 2], [3, 4]], ['a', 'c']) возвращает 0.

SELECT hasAll([[1, 2], [3, 4]], [[1, 2], [1, 2]]) возвращает 1.

indexOf(arr, x)

Возвращает индекс первого элемента x (начиная с 1), если он есть в массиве, или 0, если его нет.

Пример:

:) SELECT indexOf([1,3,NULL,NULL],NULL)

SELECT indexOf([1, 3, NULL, NULL], NULL)

┌─indexOf([1, 3, NULL, NULL], NULL)─┐
│                                 3 │
└───────────────────────────────────┘

Элементы, равные NULL, обрабатываются как обычные значения.

countEqual(arr, x)

Возвращает количество элементов массива, равных x. Эквивалентно arrayCount(elem -> elem = x, arr).

NULL обрабатывается как значение.

Пример:

SELECT countEqual([1, 2, NULL, NULL], NULL)

┌─countEqual([1, 2, NULL, NULL], NULL)─┐
│                                    2 │
└──────────────────────────────────────┘

arrayEnumerate(arr)

Возвращает массив [1, 2, 3, ..., length(arr)]

Эта функция обычно используется совместно с ARRAY JOIN. Она позволяет, после применения ARRAY JOIN, посчитать что-либо только один раз для каждого массива. Пример:

SELECT
    count() AS Reaches,
    countIf(num = 1) AS Hits
FROM test.hits
ARRAY JOIN
    GoalsReached,
    arrayEnumerate(GoalsReached) AS num
WHERE CounterID = 160656
LIMIT 10
┌─Reaches─┬──Hits─┐
│   95606 │ 31406 │
└─────────┴───────┘

В этом примере, Reaches - число достижений целей (строк, получившихся после применения ARRAY JOIN), а Hits - число хитов (строк, которые были до ARRAY JOIN). В данном случае, тот же результат можно получить проще:

SELECT
    sum(length(GoalsReached)) AS Reaches,
    count() AS Hits
FROM test.hits
WHERE (CounterID = 160656) AND notEmpty(GoalsReached)
┌─Reaches─┬──Hits─┐
│   95606 │ 31406 │
└─────────┴───────┘

Также эта функция может быть использована в функциях высшего порядка. Например, с её помощью можно достать индексы массива для элементов, удовлетворяющих некоторому условию.

arrayEnumerateUniq(arr, ...)

Возвращает массив, такого же размера, как исходный, где для каждого элемента указано, какой он по счету среди элементов с таким же значением. Например: arrayEnumerateUniq([10, 20, 10, 30]) = [1, 1, 2, 1].

Эта функция полезна при использовании ARRAY JOIN и агрегации по элементам массива. Пример:

SELECT
    Goals.ID AS GoalID,
    sum(Sign) AS Reaches,
    sumIf(Sign, num = 1) AS Visits
FROM test.visits
ARRAY JOIN
    Goals,
    arrayEnumerateUniq(Goals.ID) AS num
WHERE CounterID = 160656
GROUP BY GoalID
ORDER BY Reaches DESC
LIMIT 10
┌──GoalID─┬─Reaches─┬─Visits─┐
│   53225 │    3214 │   1097 │
│ 2825062 │    3188 │   1097 │
│   56600 │    2803 │    488 │
│ 1989037 │    2401 │    365 │
│ 2830064 │    2396 │    910 │
│ 1113562 │    2372 │    373 │
│ 3270895 │    2262 │    812 │
│ 1084657 │    2262 │    345 │
│   56599 │    2260 │    799 │
│ 3271094 │    2256 │    812 │
└─────────┴─────────┴────────┘

В этом примере, для каждого идентификатора цели, посчитано количество достижений целей (каждый элемент вложенной структуры данных Goals является достижением целей) и количество визитов. Если бы не было ARRAY JOIN, мы бы считали количество визитов как sum(Sign). Но в данном случае, строчки были размножены по вложенной структуре Goals, и чтобы после этого учесть каждый визит один раз, мы поставили условие на значение функции arrayEnumerateUniq(Goals.ID).

Функция arrayEnumerateUniq может принимать несколько аргументов - массивов одинаковых размеров. В этом случае, уникальность считается для кортежей элементов на одинаковых позициях всех массивов.

SELECT arrayEnumerateUniq([1, 1, 1, 2, 2, 2], [1, 1, 2, 1, 1, 2]) AS res
┌─res───────────┐
│ [1,2,1,1,2,1] │
└───────────────┘

Это нужно при использовании ARRAY JOIN с вложенной структурой данных и затем агрегации по нескольким элементам этой структуры.

arrayPopBack

Удаляет последний элемент из массива.

arrayPopBack(array)

Параметры

  • array - Массив.

Пример

SELECT arrayPopBack([1, 2, 3]) AS res
┌─res───┐
│ [1,2] │
└───────┘

arrayPopFront

Удаляет первый элемент из массива.

arrayPopFront(array)

Параметры

  • array - Массив.

Пример

SELECT arrayPopFront([1, 2, 3]) AS res
┌─res───┐
│ [2,3] │
└───────┘

arrayPushBack

Добавляет один элемент в конец массива.

arrayPushBack(array, single_value)

Параметры

  • array - Массив.
  • single_value - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип single_value к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "Типы данных". Может быть равно NULL. Функция добавит элемент NULL в массив, а тип элементов массива преобразует в Nullable.

Пример

SELECT arrayPushBack(['a'], 'b') AS res
┌─res───────┐
│ ['a','b'] │
└───────────┘

arrayPushFront

Добавляет один элемент в начало массива.

arrayPushFront(array, single_value)

Параметры

  • array - Массив.
  • single_value - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип single_value к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "Типы данных". Может быть равно NULL. Функция добавит элемент NULL в массив, а тип элементов массива преобразует в Nullable.

Пример

SELECT arrayPushBack(['b'], 'a') AS res
┌─res───────┐
│ ['a','b'] │
└───────────┘

arrayResize

Изменяет длину массива.

arrayResize(array, size[, extender])

Параметры

  • array — массив.
  • size — необходимая длина массива.
    • Если size меньше изначального размера массива, то массив обрезается справа.
    • Если size больше изначального размера массива, массив дополняется справа значениями extender или значениями по умолчанию для типа данных элементов массива.
  • extender — значение для дополнения массива. Может быть NULL.

Возвращаемое значение:

Массив длины size.

Примеры вызовов

SELECT arrayResize([1], 3)

┌─arrayResize([1], 3)─┐
│ [1,0,0]             │
└─────────────────────┘
SELECT arrayResize([1], 3, NULL)

┌─arrayResize([1], 3, NULL)─┐
│ [1,NULL,NULL]             │
└───────────────────────────┘

arraySlice

Возвращает срез массива.

arraySlice(array, offset[, length])

Параметры

  • array - Массив данных.
  • offset - Отступ от края массива. Положительное значение - отступ слева, отрицательное значение - отступ справа. Отсчет элементов массива начинается с 1.
  • length - Длина необходимого среза. Если указать отрицательное значение, то функция вернёт открытый срез [offset, array_length - length). Если не указать значение, то функция вернёт срез [offset, the_end_of_array].

Пример

SELECT arraySlice([1, 2, NULL, 4, 5], 2, 3) AS res
┌─res────────┐
│ [2,NULL,4] │
└────────────┘

Элементы массива равные NULL обрабатываются как обычные значения.

arraySort([func,] arr, ...)

Возвращает массив arr, отсортированный в восходящем порядке. Если задана функция func, то порядок сортировки определяется результатом применения этой функции на элементы массива arr. Если func принимает несколько аргументов, то в функцию arraySort нужно передавать несколько массивов, которые будут соответствовать аргументам функции func. Подробные примеры рассмотрены в конце описания arraySort.

Пример сортировки целочисленных значений:

SELECT arraySort([1, 3, 3, 0])
┌─arraySort([1, 3, 3, 0])─┐
│ [0,1,3,3]               │
└─────────────────────────┘

Пример сортировки строковых значений:

SELECT arraySort(['hello', 'world', '!'])
┌─arraySort(['hello', 'world', '!'])─┐
│ ['!','hello','world']              │
└────────────────────────────────────┘

Значения NULL, NaN и Inf сортируются по следующему принципу:

SELECT arraySort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf]);
┌─arraySort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf])─┐
│ [-inf,-4,1,2,3,inf,nan,nan,NULL,NULL]                     │
└───────────────────────────────────────────────────────────┘
  • Значения -Inf идут в начале массива.
  • Значения NULL идут в конце массива.
  • Значения NaN идут перед NULL.
  • Значения Inf идут перед NaN.

Функция arraySort является функцией высшего порядка — в качестве первого аргумента ей можно передать лямбда-функцию. В этом случае порядок сортировки определяется результатом применения лямбда-функции на элементы массива.

Рассмотрим пример:

SELECT arraySort((x) -> -x, [1, 2, 3]) as res;
┌─res─────┐
│ [3,2,1] │
└─────────┘

Для каждого элемента исходного массива лямбда-функция возвращает ключ сортировки, то есть [1 > -1, 2 > -2, 3 > -3]. Так как arraySort сортирует элементы в порядке возрастания ключей, результат будет [3, 2, 1]. Как можно заметить, функция x > -x устанавливает обратный порядок сортировки.

Лямбда-функция может принимать несколько аргументов. В этом случае, в функцию arraySort нужно передавать несколько массивов, которые будут соответствовать аргументам лямбда-функции (массивы должны быть одинаковой длины). Следует иметь в виду, что результат будет содержать элементы только из первого массива; элементы из всех последующих массивов будут задавать ключи сортировки. Например:

SELECT arraySort((x, y) -> y, ['hello', 'world'], [2, 1]) as res;
┌─res────────────────┐
│ ['world', 'hello'] │
└────────────────────┘

Элементы, указанные во втором массиве ([2,1]), определяют ключ сортировки для элементов из исходного массива (['hello', 'world']), то есть ['hello' > 2, 'world' > 1]. Так как лямбда-функция не использует x, элементы исходного массива не влияют на порядок сортировки. Таким образом, 'hello' будет вторым элементом в отсортированном массиве, а 'world' — первым.

Ниже приведены другие примеры.

SELECT arraySort((x, y) -> y, [0, 1, 2], ['c', 'b', 'a']) as res;
┌─res─────┐
 [2,1,0] 
└─────────┘
SELECT arraySort((x, y) -> -y, [0, 1, 2], [1, 2, 3]) as res;
┌─res─────┐
 [2,1,0] 
└─────────┘

!!! note "Примечание" Для улучшения эффективности сортировки применяется преобразование Шварца.

arrayReverseSort([func,] arr, ...)

Возвращает массив arr, отсортированный в нисходящем порядке. Если указана функция func, то массив arr сначала сортируется в порядке, который определяется функцией func, а затем отсортированный массив переворачивается. Если функция func принимает несколько аргументов, то в функцию arrayReverseSort необходимо передавать несколько массивов, которые будут соответствовать аргументам функции func. Подробные примеры рассмотрены в конце описания функции arrayReverseSort.

Пример сортировки целочисленных значений:

SELECT arrayReverseSort([1, 3, 3, 0]);
┌─arrayReverseSort([1, 3, 3, 0])─┐
│ [3,3,1,0]                      │
└────────────────────────────────┘

Пример сортировки строковых значений:

SELECT arrayReverseSort(['hello', 'world', '!']);
┌─arrayReverseSort(['hello', 'world', '!'])─┐
│ ['world','hello','!']                     │
└───────────────────────────────────────────┘

Значения NULL, NaN и Inf сортируются в следующем порядке:

SELECT arrayReverseSort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf]) as res;
┌─res───────────────────────────────────┐
 [inf,3,2,1,-4,-inf,nan,nan,NULL,NULL] 
└───────────────────────────────────────┘
  • Значения Inf идут в начале массива.
  • Значения NULL идут в конце массива.
  • Значения NaN идут перед NULL.
  • Значения -Inf идут перед NaN.

Функция arrayReverseSort является функцией высшего порядка. Вы можете передать ей в качестве первого аргумента лямбда-функцию. Например:

SELECT arrayReverseSort((x) -> -x, [1, 2, 3]) as res;
┌─res─────┐
│ [1,2,3] │
└─────────┘

В этом примере, порядок сортировки устанавливается следующим образом:

  1. Сначала исходный массив ([1, 2, 3]) сортируется в том порядке, который определяется лямбда-функцией. Результатом будет массив [3, 2, 1].
  2. Массив, который был получен на предыдущем шаге, переворачивается. То есть, получается массив [1, 2, 3].

Лямбда-функция может принимать на вход несколько аргументов. В этом случае, в функцию arrayReverseSort нужно передавать несколько массивов, которые будут соответствовать аргументам лямбда-функции (массивы должны быть одинаковой длины). Следует иметь в виду, что результат будет содержать элементы только из первого массива; элементы из всех последующих массивов будут определять ключи сортировки. Например:

SELECT arrayReverseSort((x, y) -> y, ['hello', 'world'], [2, 1]) as res;
┌─res───────────────┐
 ['hello','world'] 
└───────────────────┘

В этом примере, массив сортируется следующим образом:

  1. Сначала массив сортируется в том порядке, который определяется лямбда-функцией. Элементы, указанные во втором массиве ([2,1]), определяют ключи сортировки соответствующих элементов из исходного массива (['hello', 'world']). То есть, будет массив ['world', 'hello'].
  2. Массив, который был отсортирован на предыдущем шаге, переворачивается. Получается массив ['hello', 'world'].

Ниже приведены ещё примеры.

SELECT arrayReverseSort((x, y) -> y, [0, 1, 2], ['c', 'b', 'a']) as res;
┌─res─────┐
 [0,1,2] 
└─────────┘
SELECT arrayReverseSort((x, y) -> -y, [4, 3, 5], [1, 2, 3]) AS res;
┌─res─────┐
 [4,3,5] 
└─────────┘

arrayUniq(arr, ...)

Если передан один аргумент, считает количество разных элементов в массиве. Если передано несколько аргументов, считает количество разных кортежей из элементов на соответствующих позициях в нескольких массивах.

Если необходимо получить список уникальных элементов массива, можно воспользоваться arrayReduce('groupUniqArray', arr).

arrayJoin(arr)

Особенная функция. Смотрите раздел "Функция arrayJoin".

Оригинальная статья