> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-8c05c8a2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Документация по комбинаторам агрегатных функций

# Комбинаторы агрегатных функций

К имени агрегатной функции можно добавить суффикс. Это меняет поведение агрегатной функции.

<div id="-if">
  ## -If
</div>

Суффикс -If можно добавить к имени любой агрегатной функции. В этом случае агрегатная функция принимает дополнительный аргумент — условие (типа Uint8). Агрегатная функция обрабатывает только те строки, которые удовлетворяют условию. Если условие ни разу не выполнилось, возвращается значение по умолчанию (обычно нули или пустые строки).

Примеры: `sumIf(column, cond)`, `countIf(cond)`, `avgIf(x, cond)`, `quantilesTimingIf(level1, level2)(x, cond)`, `argMinIf(arg, val, cond)` и так далее.

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

<div id="-array">
  ## -Array
</div>

Суффикс -Array можно добавить к любой агрегатной функции. В этом случае агрегатная функция принимает аргументы типа 'Array(T)' (массивы) вместо аргументов типа 'T'. Если агрегатная функция принимает несколько аргументов, это должны быть массивы одинаковой длины. При обработке массивов агрегатная функция работает так же, как исходная агрегатная функция, применённая ко всем элементам массива.

Пример 1: `sumArray(arr)` — суммирует все элементы всех массивов 'arr'. В данном случае это можно было бы записать проще: `sum(arraySum(arr))`.

Пример 2: `uniqArray(arr)` — подсчитывает количество уникальных элементов во всех массивах 'arr'. Это также можно было бы сделать проще: `uniq(arrayJoin(arr))`, но добавить 'arrayJoin' в запрос можно не всегда.

-If и -Array можно комбинировать. Однако 'Array' должно идти первым, а затем 'If'. Примеры: `uniqArrayIf(arr, cond)`, `quantilesTimingArrayIf(level1, level2)(arr, cond)`. Из-за такого порядка аргумент 'cond' не будет массивом.

<div id="-map">
  ## -Map
</div>

Суффикс -Map можно добавить к любой агрегатной функции. Это создаст агрегатную функцию, которая принимает в качестве аргумента тип Map и отдельно агрегирует values каждого key в map с помощью указанной агрегатной функции. Результат также имеет тип Map.

**Пример**

```sql theme={null}
CREATE TABLE map_map(
    date Date,
    timeslot DateTime,
    status Map(String, UInt64)
) ENGINE = MergeTree
ORDER BY ();

INSERT INTO map_map VALUES
    ('2000-01-01', '2000-01-01 00:00:00', (['a', 'b', 'c'], [10, 10, 10])),
    ('2000-01-01', '2000-01-01 00:00:00', (['c', 'd', 'e'], [10, 10, 10])),
    ('2000-01-01', '2000-01-01 00:01:00', (['d', 'e', 'f'], [10, 10, 10])),
    ('2000-01-01', '2000-01-01 00:01:00', (['f', 'g', 'g'], [10, 10, 10]));

SELECT
    timeslot,
    sumMap(status),
    avgMap(status),
    minMap(status)
FROM map_map
GROUP BY timeslot;

┌────────────timeslot─┬─sumMap(status)───────────────────────┬─avgMap(status)───────────────────────┬─minMap(status)───────────────────────┐
│ 2000-01-01 00:00:00 │ {'a':10,'b':10,'c':20,'d':10,'e':10} │ {'a':10,'b':10,'c':10,'d':10,'e':10} │ {'a':10,'b':10,'c':10,'d':10,'e':10} │
│ 2000-01-01 00:01:00 │ {'d':10,'e':10,'f':20,'g':20}        │ {'d':10,'e':10,'f':10,'g':10}        │ {'d':10,'e':10,'f':10,'g':10}        │
└─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘
```

<div id="-simplestate">
  ## -SimpleState
</div>

При применении этого комбинатора агрегатная функция возвращает то же значение, но другого типа. Это [SimpleAggregateFunction(...)](/ru/reference/data-types/simpleaggregatefunction), который можно хранить в таблице для работы с таблицами [AggregatingMergeTree](/ru/reference/engines/table-engines/mergetree-family/aggregatingmergetree).

**Синтаксис**

```sql theme={null}
<aggFunction>SimpleState(x)
```

**Аргументы**

* `x` — Параметры агрегатной функции.

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

Значение агрегатной функции типа `SimpleAggregateFunction(...)`.

**Пример**

```sql title="Query" theme={null}
WITH anySimpleState(number) AS c SELECT toTypeName(c), c FROM numbers(1);
```

```text title="Response" theme={null}
┌─toTypeName(c)────────────────────────┬─c─┐
│ SimpleAggregateFunction(any, UInt64) │ 0 │
└──────────────────────────────────────┴───┘
```

<div id="-state">
  ## -State
</div>

Если применить этот комбинатор, агрегатная функция возвращает не итоговое значение (например, число уникальных значений для функции [uniq](/ru/reference/functions/aggregate-functions/uniq)), а промежуточное состояние агрегации (для `uniq` это хеш-таблица для вычисления числа уникальных значений). Это `AggregateFunction(...)`, которую можно использовать для дальнейшей обработки или сохранить в таблице, чтобы завершить агрегацию позже.

<Note>
  Обратите внимание: -MapState не является инвариантным для одних и тех же данных, поскольку порядок данных в промежуточном состоянии может меняться, хотя это не влияет на ингестию этих данных.
</Note>

Для работы с этими состояниями используйте:

* движок таблицы [AggregatingMergeTree](/ru/reference/engines/table-engines/mergetree-family/aggregatingmergetree).
* функцию [finalizeAggregation](/ru/reference/functions/regular-functions/other-functions#finalizeAggregation).
* функцию [runningAccumulate](/ru/reference/functions/regular-functions/other-functions#runningAccumulate).
* комбинатор [-Merge](#-merge).
* комбинатор [-MergeState](#-mergestate).

<div id="-merge">
  ## -Merge
</div>

При использовании этого комбинатора агрегатная функция принимает в качестве аргумента промежуточное состояние агрегации, объединяет состояния, завершая агрегацию, и возвращает итоговое значение.

<div id="-mergestate">
  ## -MergeState
</div>

Объединяет промежуточные состояния агрегации так же, как комбинатор -Merge. Однако возвращает не итоговое значение, а промежуточное состояние агрегации, как и комбинатор -State.

<div id="-foreach">
  ## -ForEach
</div>

Преобразует агрегатную функцию для таблиц в агрегатную функцию для массивов, которая агрегирует соответствующие элементы массивов и возвращает массив результатов. Например, `sumForEach` для массивов `[1, 2]`, `[3, 4, 5]`and`[6, 7]` возвращает результат `[10, 13, 5]` после суммирования соответствующих элементов.

<div id="-distinct">
  ## -Distinct
</div>

Каждая уникальная комбинация аргументов будет учитываться при агрегации только один раз. Повторяющиеся значения игнорируются.
Примеры: `sum(DISTINCT x)` (или `sumDistinct(x)`), `groupArray(DISTINCT x)` (или `groupArrayDistinct(x)`), `corrStable(DISTINCT x, y)` (или `corrStableDistinct(x, y)`) и так далее.

<div id="-ordefault">
  ## -OrDefault
</div>

Изменяет поведение агрегатной функции.

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

`-OrDefault` можно использовать с другими комбинаторами.

**Синтаксис**

```sql theme={null}
<aggFunction>OrDefault(x)
```

**Аргументы**

* `x` — Параметры агрегатной функции.

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

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

Тип зависит от используемой агрегатной функции.

**Пример**

```sql title="Query" theme={null}
SELECT avg(number), avgOrDefault(number) FROM numbers(0)
```

```text title="Response" theme={null}
┌─avg(number)─┬─avgOrDefault(number)─┐
│         nan │                    0 │
└─────────────┴──────────────────────┘
```

Также `-OrDefault` можно использовать с другими комбинаторами. Это полезно, когда агрегатная функция не принимает пустой ввод.

```sql title="Query" theme={null}
SELECT avgOrDefaultIf(x, x > 10)
FROM
(
    SELECT toDecimal32(1.23, 2) AS x
)
```

```text title="Response" theme={null}
┌─avgOrDefaultIf(x, greater(x, 10))─┐
│                              0.00 │
└───────────────────────────────────┘
```

<div id="-ornull">
  ## -OrNull
</div>

Изменяет поведение агрегатной функции.

Этот комбинатор преобразует результат агрегатной функции в тип данных [Nullable](/ru/reference/data-types/nullable). Если у агрегатной функции нет значений для вычисления, возвращается [NULL](/ru/reference/settings/formats#input_format_null_as_default).

`-OrNull` можно использовать с другими комбинаторами.

**Синтаксис**

```sql theme={null}
<aggFunction>OrNull(x)
```

**Аргументы**

* `x` — параметры агрегатной функции.

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

* Результат агрегатной функции, приведённый к типу данных `Nullable`.
* `NULL`, если агрегировать нечего.

Тип: `Nullable(aggregate function return type)`.

**Пример**

Добавьте `-orNull` в конец имени агрегатной функции.

```sql title="Query" theme={null}
SELECT sumOrNull(number), toTypeName(sumOrNull(number)) FROM numbers(10) WHERE number > 10
```

```text title="Response" theme={null}
┌─sumOrNull(number)─┬─toTypeName(sumOrNull(number))─┐
│              ᴺᵁᴸᴸ │ Nullable(UInt64)              │
└───────────────────┴───────────────────────────────┘
```

Также `-OrNull` можно использовать с другими комбинаторами. Это полезно, когда агрегатная функция не принимает пустой вход.

```sql title="Query" theme={null}
SELECT avgOrNullIf(x, x > 10)
FROM
(
    SELECT toDecimal32(1.23, 2) AS x
)
```

```text title="Response" theme={null}
┌─avgOrNullIf(x, greater(x, 10))─┐
│                           ᴺᵁᴸᴸ │
└────────────────────────────────┘
```

<div id="-resample">
  ## -Resample
</div>

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

```sql theme={null}
<aggFunction>Resample(start, end, step)(<aggFunction_params>, resampling_key)
```

**Аргументы**

* `start` — Начальное значение всего требуемого интервала для значений `resampling_key`.
* `stop` — Конечное значение всего требуемого интервала для значений `resampling_key`. Этот интервал не включает значение `stop` `[start, stop)`.
* `step` — Шаг разбиения всего интервала на подынтервалы. `aggFunction` выполняется для каждого из этих подынтервалов независимо.
* `resampling_key` — Столбец, значения которого используются для разбиения данных на интервалы.
* `aggFunction_params` — Параметры `aggFunction`.

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

* Массив результатов `aggFunction` для каждого подынтервала.

**Пример**

Рассмотрим таблицу `people` со следующими данными:

```text theme={null}
┌─name───┬─age─┬─wage─┐
│ John   │  16 │   10 │
│ Alice  │  30 │   15 │
│ Mary   │  35 │    8 │
│ Evelyn │  48 │ 11.5 │
│ David  │  62 │  9.9 │
│ Brian  │  60 │   16 │
└────────┴─────┴──────┘
```

Давайте получим имена людей, возраст которых попадает в интервалы `[30,60)` и `[60,75)`. Поскольку возраст представлен целыми числами, получаем интервалы возрастов `[30, 59]` и `[60,74]`.

Чтобы агрегировать имена в массив, используем агрегатную функцию [groupArray](/ru/reference/functions/aggregate-functions/groupArray). Она принимает один аргумент. В нашем случае это столбец `name`. Функция `groupArrayResample` должна использовать столбец `age`, чтобы агрегировать имена по возрасту. Чтобы задать нужные интервалы, передаём в функцию `groupArrayResample` аргументы `30, 75, 30`.

```sql theme={null}
SELECT groupArrayResample(30, 75, 30)(name, age) FROM people
```

```text theme={null}
┌─groupArrayResample(30, 75, 30)(name, age)─────┐
│ [['Alice','Mary','Evelyn'],['David','Brian']] │
└───────────────────────────────────────────────┘
```

Рассмотрим результаты.

`John` не попадает в выборку, потому что он слишком молод. Остальные люди распределены по указанным возрастным интервалам.

Теперь посчитаем общее число людей и их среднюю заработную плату в указанных возрастных интервалах.

```sql theme={null}
SELECT
    countResample(30, 75, 30)(name, age) AS amount,
    avgResample(30, 75, 30)(wage, age) AS avg_wage
FROM people
```

```text theme={null}
┌─amount─┬─avg_wage──────────────────┐
│ [3,2]  │ [11.5,12.949999809265137] │
└────────┴───────────────────────────┘
```

<div id="-argmin">
  ## -ArgMin
</div>

Суффикс -ArgMin можно добавить к имени любой агрегатной функции. В этом случае агрегатная функция принимает дополнительный аргумент, которым может быть любое выражение, поддерживающее сравнение. Агрегатная функция обрабатывает только те строки, для которых указанное дополнительное выражение имеет минимальное значение.

Примеры: `sumArgMin(column, expr)`, `countArgMin(expr)`, `avgArgMin(x, expr)` и так далее.

<div id="-argmax">
  ## -ArgMax
</div>

Аналогично суффиксу -ArgMin, но обрабатывает только строки с максимальным значением указанного дополнительного выражения.

<div id="related-content">
  ## См. также
</div>

* Блог: [Использование агрегатных комбинаторов в ClickHouse](https://clickhouse.com/blog/aggregate-functions-combinators-in-clickhouse-for-arrays-maps-and-states)
