# Функции по работе с массивами ## empty Возвращает 1 для пустого массива, и 0 для непустого массива. Тип результата - UInt8. Функция также работает для строк. ## notEmpty Возвращает 0 для пустого массива, и 1 для непустого массива. Тип результата - UInt8. Функция также работает для строк. ## length {#array_functions-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](../../data_types/array.md) **Пример** ```sql 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 для чисел, пустая строка для строк и т. п.). ## 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) {#array_functions-arrayenumerate} Возвращает массив \[1, 2, 3, ..., length(arr)\] Эта функция обычно используется совместно с ARRAY JOIN. Она позволяет, после применения ARRAY JOIN, посчитать что-либо только один раз для каждого массива. Пример: ```sql 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). В данном случае, тот же результат можно получить проще: ```sql 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 и агрегации по элементам массива. Пример: ```sql 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 может принимать несколько аргументов - массивов одинаковых размеров. В этом случае, уникальность считается для кортежей элементов на одинаковых позициях всех массивов. ```sql 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` - Массив. **Пример** ```sql SELECT arrayPopBack([1, 2, 3]) AS res ``` ``` ┌─res───┐ │ [1,2] │ └───────┘ ``` ## arrayPopFront Удаляет первый элемент из массива. ``` arrayPopFront(array) ``` **Параметры** - `array` - Массив. **Пример** ```sql SELECT arrayPopFront([1, 2, 3]) AS res ``` ``` ┌─res───┐ │ [2,3] │ └───────┘ ``` ## arrayPushBack Добавляет один элемент в конец массива. ``` arrayPushBack(array, single_value) ``` **Параметры** - `array` - Массив. - `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../../data_types/index.md#data_types)". Может быть равно `NULL`. Функция добавит элемент `NULL` в массив, а тип элементов массива преобразует в `Nullable`. **Пример** ```sql SELECT arrayPushBack(['a'], 'b') AS res ``` ``` ┌─res───────┐ │ ['a','b'] │ └───────────┘ ``` ## arrayPushFront Добавляет один элемент в начало массива. ``` arrayPushFront(array, single_value) ``` **Параметры** - `array` - Массив. - `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../../data_types/index.md#data_types)". Может быть равно `NULL`. Функция добавит элемент `NULL` в массив, а тип элементов массива преобразует в `Nullable`. **Пример** ```sql 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]`. **Пример** ```sql SELECT arraySlice([1, 2, NULL, 4, 5], 2, 3) AS res ``` ``` ┌─res────────┐ │ [2,NULL,4] │ └────────────┘ ``` Элементы массива равные `NULL` обрабатываются как обычные значения. ## arraySort([func,] arr, ...) Возвращает массив `arr`, отсортированный в восходящем порядке. Пример сортировки целочисленных значений: ``` sql SELECT arraySort([1, 3, 3, 0]) ``` ``` ┌─arraySort([1, 3, 3, 0])─┐ │ [0,1,3,3] │ └─────────────────────────┘ ``` Пример сортировки строковых значений: ``` sql SELECT arraySort(['hello', 'world', '!']) ``` ``` ┌─arraySort(['hello', 'world', '!'])─┐ │ ['!','hello','world'] │ └────────────────────────────────────┘ ``` Значения `NULL`, `NaN` и `Inf` сортируются по следующему принципу: ``` sql 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` является [функцией высшего порядка](higher_order_functions.md) — в качестве первого аргумента ей можно передать лямбда-функцию. В этом случае порядок сортировки определяется результатом применения лямбда-функции на элементы массива. Ниже приведён пример. ``` sql SELECT arraySort(lambda(tuple(x, y), y), ['hello', 'world'], [2, 1]) as res; ``` ``` ┌─res────────────────┐ │ ['world', 'hello'] │ └────────────────────┘ ``` Элементы, указанные во втором массиве ([2,1]), определяют позицию соответствующих элементов из исходного массива (['hello', 'world']). То есть, 'hello' будет вторым элементом в отсортированном массиве, а 'world' — первым. Ниже приведен ещё один пример. В нём для описания лямбда-функции используется стрелочка (оператор `->`): ``` sql SELECT arraySort((x, y) -> y, [0, 1, 2], [2, 1, 3]) as res; ``` ``` sql ┌─res─────┐ │ [1,0,2] │ └─────────┘ ``` Для улучшения эффективности сортировки применяется [Преобразование Шварца](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A8%D0%B2%D0%B0%D1%80%D1%86%D0%B0). ## arrayReverseSort([func,] arr, ...) Возвращает массив `arr`, отсортированный в нисходящем порядке. Пример сортировки целочисленных значений: ``` sql SELECT arrayReverseSort([1, 3, 3, 0]); ``` ``` ┌─arrayReverseSort([1, 3, 3, 0])─┐ │ [3,3,1,0] │ └────────────────────────────────┘ ``` Пример сортировки строковых значений: ``` sql SELECT arrayReverseSort(['hello', 'world', '!']); ``` ``` ┌─arrayReverseSort(['hello', 'world', '!'])─┐ │ ['world','hello','!'] │ └───────────────────────────────────────────┘ ``` Значения `NULL`, `NaN` и `Inf` сортируются в следующем порядке: ``` sql SELECT arrayReverseSort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf]) as res; ``` ``` sql ┌─res───────────────────────────────────┐ │ [inf,3,2,1,-4,-inf,nan,nan,NULL,NULL] │ └───────────────────────────────────────┘ ``` - Значения `Inf` идут в начале массива. - Значения `NULL` идут в конце массива. - Значения `NaN` идут перед `NULL`. - Значения `-Inf` идут перед `NaN`. Функция `arrayReverseSort` является [функцией высшего порядка](higher_order_functions.md). Вы можете передать ей в качестве первого аргумента лямбда-функцию. Например: ``` sql SELECT arrayReverseSort((x, y) -> y, ['hello', 'world'], [2, 1]) as res; ``` ``` sql ┌─res───────────────┐ │ ['hello','world'] │ └───────────────────┘ ``` В этом случае, массив сортируется следующим образом: 1. Сначала массив сортируется в том порядке, который определяется лямбда-функцией. Элементы, указанные во втором массиве ([2,1]), определяют позицию соответствующих элементов из исходного массива (['hello', 'world']). То есть, промежуточным результатом будет массив ['world', 'hello']. 2. Массив, который был отсортирован на предыдущем шаге, переворачивается. Получается массив ['hello', 'world']. Ниже приведён еще один пример. ``` sql SELECT arrayReverseSort((x, y) -> y, [4, 3, 5], [3, 1, 2]) AS res; ``` ``` sql ┌─res─────┐ │ [4,5,3] │ └─────────┘ ``` ## arrayUniq(arr, ...) Если передан один аргумент, считает количество разных элементов в массиве. Если передано несколько аргументов, считает количество разных кортежей из элементов на соответствующих позициях в нескольких массивах. Если необходимо получить список уникальных элементов массива, можно воспользоваться arrayReduce('groupUniqArray', arr). ## arrayJoin(arr) Особенная функция. Смотрите раздел ["Функция arrayJoin"](array_join.md#functions_arrayjoin). [Оригинальная статья](https://clickhouse.yandex/docs/ru/query_language/functions/array_functions/)