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

> Документация об условных функциях

# Условные функции

<div id="overview">
  ## Обзор
</div>

<div id="using-conditional-results-directly">
  ### Прямое использование результатов условных выражений
</div>

Условные выражения всегда возвращают `0`, `1` или `NULL`. Поэтому их результаты можно использовать напрямую, например так:

```sql theme={null}
SELECT left < right AS is_small
FROM LEFT_RIGHT

┌─is_small─┐
│     ᴺᵁᴸᴸ │
│        1 │
│        0 │
│        0 │
│     ᴺᵁᴸᴸ │
└──────────┘
```

<div id="null-values-in-conditionals">
  ### Значения NULL в условных выражениях
</div>

Если в условных выражениях участвуют значения `NULL`, результатом также будет `NULL`.

```sql theme={null}
SELECT
    NULL < 1,
    2 < NULL,
    NULL < NULL,
    NULL = NULL

┌─less(NULL, 1)─┬─less(2, NULL)─┬─less(NULL, NULL)─┬─equals(NULL, NULL)─┐
│ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ             │ ᴺᵁᴸᴸ               │
└───────────────┴───────────────┴──────────────────┴────────────────────┘
```

Поэтому, если типы — `Nullable`, запросы следует составлять особенно внимательно.

Следующий пример это показывает: он завершается ошибкой, потому что в `multiIf` не добавлено условие с равенством.

```sql theme={null}
SELECT
    left,
    right,
    multiIf(left < right, 'left is smaller', left > right, 'right is smaller', 'Both equal') AS faulty_result
FROM LEFT_RIGHT

┌─left─┬─right─┬─faulty_result────┐
│ ᴺᵁᴸᴸ │     4 │ Both equal       │
│    1 │     3 │ left is smaller  │
│    2 │     2 │ Both equal       │
│    3 │     1 │ right is smaller │
│    4 │  ᴺᵁᴸᴸ │ Both equal       │
└──────┴───────┴──────────────────┘
```

<div id="case-statement">
  ### Оператор CASE
</div>

Выражение CASE в ClickHouse предоставляет условную логику, аналогичную оператору CASE в SQL. Оно вычисляет условия и возвращает значения на основе первого совпадения.

ClickHouse поддерживает две формы CASE:

1. `CASE WHEN ... THEN ... ELSE ... END`
   <br />
   Эта форма обеспечивает максимальную гибкость и внутренне реализована с помощью функции [multiIf](/ru/reference/functions/regular-functions/conditional-functions#multiIf). Каждое условие вычисляется независимо, а выражения могут включать неконстантные значения.

```sql theme={null}
SELECT
    number,
    CASE
        WHEN number % 2 = 0 THEN number + 1
        WHEN number % 2 = 1 THEN number * 10
        ELSE number
    END AS result
FROM system.numbers
WHERE number < 5;

-- преобразуется в
SELECT
    number,
    multiIf((number % 2) = 0, number + 1, (number % 2) = 1, number * 10, number) AS result
FROM system.numbers
WHERE number < 5

┌─number─┬─result─┐
│      0 │      1 │
│      1 │     10 │
│      2 │      3 │
│      3 │     30 │
│      4 │      5 │
└────────┴────────┘

5 rows in set. Elapsed: 0.002 sec.
```

2. `CASE <expr> WHEN <val1> THEN ... WHEN <val2> THEN ... ELSE ... END`
   <br />
   Эта более компактная форма оптимизирована для сопоставления с константными значениями и внутри использует `caseWithExpression()`.

Например, следующий вариант является допустимым:

```sql theme={null}
SELECT
    number,
    CASE number
        WHEN 0 THEN 100
        WHEN 1 THEN 200
        ELSE 0
    END AS result
FROM system.numbers
WHERE number < 3;

-- преобразуется в

SELECT
    number,
    caseWithExpression(number, 0, 100, 1, 200, 0) AS result
FROM system.numbers
WHERE number < 3

┌─number─┬─result─┐
│      0 │    100 │
│      1 │    200 │
│      2 │      0 │
└────────┴────────┘

3 rows in set. Elapsed: 0.002 sec.
```

Эта форма также не требует, чтобы возвращаемые выражения были константами.

```sql theme={null}
SELECT
    number,
    CASE number
        WHEN 0 THEN number + 1
        WHEN 1 THEN number * 10
        ELSE number
    END
FROM system.numbers
WHERE number < 3;

-- преобразуется в

SELECT
    number,
    caseWithExpression(number, 0, number + 1, 1, number * 10, number)
FROM system.numbers
WHERE number < 3

┌─number─┬─caseWithExpr⋯0), number)─┐
│      0 │                        1 │
│      1 │                       10 │
│      2 │                        2 │
└────────┴──────────────────────────┘

3 rows in set. Elapsed: 0.001 sec.
```

<div id="caveats">
  #### Ограничения
</div>

ClickHouse определяет тип результата выражения CASE (или его внутреннего эквивалента, например `multiIf`) до вычисления каких-либо условий. Это важно, когда возвращаемые выражения различаются по типу, например используют разные часовые пояса или числовые типы.

* Тип результата выбирается на основе наибольшего совместимого типа среди всех ветвей.
* После выбора этого типа все остальные ветви неявно приводятся к нему — даже если их логика никогда не будет выполнена во время исполнения.
* Для таких типов, как DateTime64, где часовой пояс является частью сигнатуры типа, это может приводить к неожиданному поведению: часовой пояс, встретившийся первым, может использоваться для всех ветвей, даже если в других ветвях указаны другие часовые пояса.

Например, ниже все строки возвращают временную метку в часовом поясе первой совпавшей ветви, то есть `Asia/Kolkata`

```sql theme={null}
SELECT
    number,
    CASE
        WHEN number = 0 THEN fromUnixTimestamp64Milli(0, 'Asia/Kolkata')
        WHEN number = 1 THEN fromUnixTimestamp64Milli(0, 'America/Los_Angeles')
        ELSE fromUnixTimestamp64Milli(0, 'UTC')
    END AS tz
FROM system.numbers
WHERE number < 3;

-- преобразуется в

SELECT
    number,
    multiIf(number = 0, fromUnixTimestamp64Milli(0, 'Asia/Kolkata'), number = 1, fromUnixTimestamp64Milli(0, 'America/Los_Angeles'), fromUnixTimestamp64Milli(0, 'UTC')) AS tz
FROM system.numbers
WHERE number < 3

┌─number─┬──────────────────────tz─┐
│      0 │ 1970-01-01 05:30:00.000 │
│      1 │ 1970-01-01 05:30:00.000 │
│      2 │ 1970-01-01 05:30:00.000 │
└────────┴─────────────────────────┘

3 rows in set. Elapsed: 0.011 sec.
```

Здесь ClickHouse видит несколько типов возвращаемого значения `DateTime64(3, <timezone>)`. В качестве общего типа он выводит `DateTime64(3, 'Asia/Kolkata'` — первый встретившийся вариант, неявно приводя к нему другие ветви.

Это можно исправить, преобразовав значение в строку, чтобы сохранить нужное форматирование часового пояса:

```sql theme={null}
SELECT
    number,
    multiIf(
        number = 0, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'Asia/Kolkata'),
        number = 1, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'America/Los_Angeles'),
        formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'UTC')
    ) AS tz
FROM system.numbers
WHERE number < 3;

-- преобразуется в

SELECT
    number,
    multiIf(number = 0, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'Asia/Kolkata'), number = 1, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'America/Los_Angeles'), formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'UTC')) AS tz
FROM system.numbers
WHERE number < 3

┌─number─┬─tz──────────────────┐
│      0 │ 1970-01-01 05:30:00 │
│      1 │ 1969-12-31 16:00:00 │
│      2 │ 1970-01-01 00:00:00 │
└────────┴─────────────────────┘

3 rows in set. Elapsed: 0.002 sec.
```

{/*AUTOGENERATED_START*/}

<div id="clamp">
  ## clamp
</div>

Добавленный в: v24.5.0

Ограничивает значение указанными минимальной и максимальной границами.

Если значение меньше минимума, возвращает минимум. Если значение больше максимума, возвращает максимум. В противном случае возвращает само значение.

Все аргументы должны быть сравнимых типов. Тип результата — наибольший совместимый тип среди всех аргументов.

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

```sql theme={null}
clamp(value, min, max)
```

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

* `value` — Значение, которое нужно привести к диапазону. - `min` — Нижняя граница. - `max` — Верхняя граница.

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

Возвращает значение, приведённое к диапазону \[min, max].

**Примеры**

**Базовое использование**

```sql title=Query theme={null}
SELECT clamp(5, 1, 10) AS result;
```

```response title=Response theme={null}
┌─result─┐
│      5 │
└────────┘
```

**Значение ниже минимума**

```sql title=Query theme={null}
SELECT clamp(-3, 0, 7) AS result;
```

```response title=Response theme={null}
┌─result─┐
│      0 │
└────────┘
```

**Значение превышает максимум**

```sql title=Query theme={null}
SELECT clamp(15, 0, 7) AS result;
```

```response title=Response theme={null}
┌─result─┐
│      7 │
└────────┘
```

<div id="greatest">
  ## greatest
</div>

Добавленный в: v1.1.0

Возвращает наибольшее значение среди аргументов.
Аргументы со значением `NULL` игнорируются.

* Для массивов возвращает лексикографически наибольший массив.
* Для типов `DateTime` тип результата повышается до наиболее широкого типа (например, до `DateTime64`, если он используется вместе с `DateTime32`).

<Info>
  **Используйте настройку `least_greatest_legacy_null_behavior`, чтобы изменить поведение `NULL`**

  В версии [24.12](/ru/resources/changelogs/oss/2024#a-id2412a-clickhouse-release-2412-2024-12-19) было внесено несовместимое с предыдущими версиями изменение: значения `NULL` игнорируются, тогда как ранее функция возвращала `NULL`, если один из аргументов был `NULL`.
  Чтобы сохранить прежнее поведение, установите для настройки `least_greatest_legacy_null_behavior` (по умолчанию: `false`) значение `true`.
</Info>

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

```sql theme={null}
greatest(x1[, x2, ...])
```

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

* `x1[, x2, ...]` — Одно или несколько значений для сравнения. Все аргументы должны быть сравнимых типов. [`Any`](/ru/reference/data-types)

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

Возвращает наибольшее значение среди аргументов; результат приводится к наибольшему совместимому типу. [`Any`](/ru/reference/data-types)

**Примеры**

**Числовые типы**

```sql title=Query theme={null}
SELECT greatest(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
-- Возвращаемый тип — Float64, так как UInt8 должен быть приведён к 64-битному типу для сравнения.
```

```response title=Response theme={null}
┌─result─┬─type────┐
│      3 │ Float64 │
└────────┴─────────┘
```

**Массивы**

```sql title=Query theme={null}
SELECT greatest(['hello'], ['there'], ['world']);
```

```response title=Response theme={null}
┌─greatest(['hello'], ['there'], ['world'])─┐
│ ['world']                                 │
└───────────────────────────────────────────┘
```

**Типы DateTime**

```sql title=Query theme={null}
SELECT greatest(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3));
-- Возвращаемый тип — DateTime64, так как DateTime32 должен быть приведён к 64-битному формату для сравнения.
```

```response title=Response theme={null}
┌─greatest(toD⋯(now(), 3))─┐
│  2025-05-28 15:50:53.000 │
└──────────────────────────┘
```

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

Добавленный в: v1.1.0

Выполняет условное ветвление.

* Если условие `cond` вычисляется в ненулевое значение, функция возвращает результат выражения `then`.
* Если `cond` вычисляется в ноль или NULL, возвращается результат выражения `else`.

Параметр [`short_circuit_function_evaluation`](/ru/reference/settings/session-settings#short_circuit_function_evaluation) определяет, используется ли укороченное вычисление.

Если он включен, выражение `then` вычисляется только для строк, где `cond` истинно, а выражение `else` — только там, где `cond` ложно.

Например, при укороченном вычислении исключение деления на ноль не генерируется при выполнении следующего запроса:

```sql theme={null}
SELECT if(number = 0, 0, intDiv(42, number)) FROM numbers(10)
```

`then` и `else` должны быть одного или близкого типа.

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

```sql theme={null}
if(cond, then, else)
```

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

* `cond` — Проверяемое условие. [`UInt8`](/ru/reference/data-types/int-uint) или [`Nullable(UInt8)`](/ru/reference/data-types/nullable) или [`NULL`](/ru/reference/syntax#null)
* `then` — Выражение, возвращаемое, если `cond` равно `true`. - `else` — Выражение, возвращаемое, если `cond` равно `false` или `NULL`.

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

Результат одного из выражений `then` или `else` в зависимости от условия `cond`.

**Примеры**

**Пример использования**

```sql title=Query theme={null}
SELECT if(1, 2 + 2, 2 + 6) AS res;
```

```response title=Response theme={null}
┌─res─┐
│   4 │
└─────┘
```

<div id="least">
  ## least
</div>

Добавленный в: v1.1.0

Возвращает наименьшее значение среди аргументов.
Аргументы `NULL` игнорируются.

* Для массивов возвращает лексикографически наименьший массив.
* Для типов DateTime тип результата повышается до наибольшего типа (например, DateTime64, если он используется вместе с DateTime32).

<Info>
  **Используйте настройку `least_greatest_legacy_null_behavior`, чтобы изменить поведение `NULL`**

  В версии [24.12](/ru/resources/changelogs/oss/2024#a-id2412a-clickhouse-release-2412-2024-12-19) было внесено несовместимое с предыдущим поведением изменение: значения `NULL` теперь игнорируются, тогда как раньше функция возвращала `NULL`, если один из аргументов был `NULL`.
  Чтобы сохранить прежнее поведение, установите для настройки `least_greatest_legacy_null_behavior` (по умолчанию: `false`) значение `true`.
</Info>

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

```sql theme={null}
least(x1[, x2, ...])
```

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

* `x1[, x2, ...]` — Одно или несколько значений для сравнения. Все аргументы должны быть сравнимых типов. [`Any`](/ru/reference/data-types)

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

Возвращает наименьшее значение среди аргументов, приведённое к наибольшему совместимому типу. [`Any`](/ru/reference/data-types)

**Примеры**

**Числовые типы**

```sql title=Query theme={null}
SELECT least(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
-- Возвращаемый тип — Float64, так как UInt8 должен быть приведён к 64-битному типу для сравнения.
```

```response title=Response theme={null}
┌─result─┬─type────┐
│      1 │ Float64 │
└────────┴─────────┘
```

**Массивы**

```sql title=Query theme={null}
SELECT least(['hello'], ['there'], ['world']);
```

```response title=Response theme={null}
┌─least(['hell⋯ ['world'])─┐
│ ['hello']                │
└──────────────────────────┘
```

**Типы DateTime**

```sql title=Query theme={null}
SELECT least(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3));
-- Возвращаемый тип — DateTime64, так как DateTime32 должен быть приведён к 64-битному типу для сравнения.
```

```response title=Response theme={null}
┌─least(toDate⋯(now(), 3))─┐
│  2025-05-27 15:55:20.000 │
└──────────────────────────┘
```

<div id="multiIf">
  ## multiIf
</div>

Добавленный в: v1.1.0

Позволяет более компактно записывать оператор [`CASE`](/ru/reference/operators#conditional-expression) в запросе.
Вычисляет каждое условие по порядку. Для первого условия, которое истинно (ненулевое и не `NULL`), возвращает значение соответствующей ветви.
Если ни одно из условий не истинно, возвращает значение `else`.

Параметр [`short_circuit_function_evaluation`](/ru/reference/settings/session-settings#short_circuit_function_evaluation) определяет,
используется ли укороченное вычисление. Если оно включено, выражение `then_i` вычисляется только для строк, где
`((NOT cond_1) AND ... AND (NOT cond_{i-1}) AND cond_i)` истинно.

Например, при укороченном вычислении исключение деления на ноль не возникает при выполнении следующего запроса:

```sql theme={null}
SELECT multiIf(number = 2, intDiv(1, number), number = 5) FROM numbers(10)
```

Все выражения в ветвях и `else` должны иметь общий супертип. Условия `NULL` считаются ложными.

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

```sql theme={null}
multiIf(cond_1, then_1, cond_2, then_2, ..., else)
```

**Псевдонимы**: `caseWithoutExpression`, `caseWithoutExpr`

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

* `cond_N` — N-е вычисляемое условие, которое определяет, будет ли возвращено `then_N`. [`UInt8`](/ru/reference/data-types/int-uint) или [`Nullable(UInt8)`](/ru/reference/data-types/nullable) или [`NULL`](/ru/reference/syntax#null)
* `then_N` — Результат функции, если `cond_N` имеет значение `true`. - `else` — Результат функции, если ни одно из условий не имеет значение `true`.

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

Возвращает результат `then_N` для соответствующего `cond_N`, в противном случае возвращает значение `else`.

**Примеры**

**Пример использования**

```sql title=Query theme={null}
CREATE TABLE LEFT_RIGHT (left Nullable(UInt8), right Nullable(UInt8)) ENGINE = Memory;
INSERT INTO LEFT_RIGHT VALUES (NULL, 4), (1, 3), (2, 2), (3, 1), (4, NULL);

SELECT
    left,
    right,
    multiIf(left < right, 'left is smaller', left > right, 'left is greater', left = right, 'Both equal', 'Null value') AS result
FROM LEFT_RIGHT;
```

```response title=Response theme={null}
┌─left─┬─right─┬─result──────────┐
│ ᴺᵁᴸᴸ │     4 │ Null value      │
│    1 │     3 │ left is smaller │
│    2 │     2 │ Both equal      │
│    3 │     1 │ left is greater │
│    4 │  ᴺᵁᴸᴸ │ Null value      │
└──────┴───────┴─────────────────┘
```
