Агрегатные функции работают обычным образом, как и ожидают специалисты по базам данных.
ClickHouse также поддерживает:
- Параметрические агрегатные функции, которые принимают дополнительные параметры помимо столбцов.
- Комбинаторы, которые изменяют поведение агрегатных функций.
Обработка NULL
При агрегации все аргументы со значением NULL пропускаются. Если у агрегации несколько аргументов, игнорируется любая строка, в которой один или несколько из них имеют значение NULL.
Из этого правила есть исключение: функции first_value, last_value и их псевдонимы (any и anyLast соответственно), если за ними следует модификатор RESPECT NULLS. Например, FIRST_VALUE(b) RESPECT NULLS.
Примеры:
Рассмотрим следующую таблицу:
┌─x─┬────y─┐
│ 1 │ 2 │
│ 2 │ ᴺᵁᴸᴸ │
│ 3 │ 2 │
│ 3 │ 3 │
│ 3 │ ᴺᵁᴸᴸ │
└───┴──────┘Допустим, вам нужно суммировать значения в столбце y:
SELECT sum(y) FROM t_null_big┌─sum(y)─┐
│ 7 │
└────────┘Теперь вы можете использовать функцию groupArray, чтобы создать массив из столбца y:
SELECT groupArray(y) FROM t_null_big┌─groupArray(y)─┐
│ [2,2,3] │
└───────────────┘groupArray не включает NULL в результирующий массив.
Вы можете использовать COALESCE, чтобы заменить NULL на значение, подходящее для вашего сценария использования. Например, avg(COALESCE(column, 0)) будет использовать значение столбца при агрегации или ноль, если это NULL:
SELECT
avg(y),
avg(coalesce(y, 0))
FROM t_null_big┌─────────────avg(y)─┬─avg(coalesce(y, 0))─┐
│ 2.3333333333333335 │ 1.4 │
└────────────────────┴─────────────────────┘Также можно использовать Tuple, чтобы обойти поведение, связанное с пропуском NULL. Tuple, содержащий только значение NULL, сам не является NULL, поэтому агрегатные функции не будут пропускать эту строку из-за этого значения NULL.
SELECT
groupArray(y),
groupArray(tuple(y)).1
FROM t_null_big;
┌Обратите внимание, что агрегации пропускаются, если столбцы используются в качестве аргументов агрегатной функции. Например, count без параметров (count()) или с константными параметрами (count(1)) будет подсчитывать все строки в блоке (независимо от значения столбца GROUP BY, так как он не является аргументом), тогда как count(column) вернет только количество строк, в которых column не равно NULL.
SELECT
v,
count(1),
count(v)
FROM
(
SELECT if(number < 10, NULL, number % 3) AS v
FROM numbers(15)
)
GROUP BY v
┌И вот пример first_value с RESPECT NULLS, где видно, что входные значения NULL учитываются и возвращается первое прочитанное значение — независимо от того, равно оно NULL или нет:
SELECT
col || '_' || ((col + 1) * 5 - 1) AS range,
first_value(odd_or_null) AS first,
first_value(odd_or_null) IGNORE NULLS as first_ignore_null,
first_value(odd_or_null) RESPECT NULLS as first_respect_nulls
FROM
(
SELECT
intDiv(number, 5) AS col,
if(number % 2 == 0, NULL, number) AS odd_or_null
FROM numbers(15)
)
GROUP BY col
ORDER BY col
┌