ClickHouse/docs/ru/sql-reference/operators/index.md
2022-04-09 07:29:05 -06:00

17 KiB
Raw Blame History

sidebar_position sidebar_label
38 Операторы

Операторы

Все операторы преобразуются в соответствующие функции на этапе парсинга запроса, с учётом их приоритетов и ассоциативности. Далее будут перечислены группы операторов в порядке их приоритета (чем выше, тем раньше оператор связывается со своими аргументами).

Операторы доступа

a[N] - доступ к элементу массива, функция arrayElement(a, N).

a.N - доступ к элементу кортежа, функция tupleElement(a, N).

Оператор числового отрицания

-a - функция negate(a).

Для чисел в кортеже также может быть использована tupleNegate.

Операторы умножения и деления

a * b - функция multiply(a, b)

Для умножения кортежа на число также может быть использована tupleMultiplyByNumber, для скалярного произведения: dotProduct.

a / b - функция divide(a, b)

Для деления кортежа на число также может быть использована tupleDivideByNumber.

a % b - функция modulo(a, b)

Операторы сложения и вычитания

a + b - функция plus(a, b)

Для сложения кортежей также может быть использована tuplePlus.

a - b - функция minus(a, b)

Для вычитания кортежей также может быть использована tupleMinus.

Операторы сравнения

a = b - функция equals(a, b)

a == b - функция equals(a, b)

a != b - функция notEquals(a, b)

a <> b - функция notEquals(a, b)

a <= b - функция lessOrEquals(a, b)

a >= b - функция greaterOrEquals(a, b)

a < b - функция less(a, b)

a > b - функция greater(a, b)

a LIKE s - функция like(a, b)

a NOT LIKE s - функция notLike(a, b)

a ILIKE s функция ilike(a, b)

a BETWEEN b AND c - равнозначно a >= b AND a <= c

a NOT BETWEEN b AND c - равнозначно a < b OR a > c

Операторы для работы с множествами

Смотрите операторы IN и оператор EXISTS.

a IN ... - функция in(a, b)

a NOT IN ... - функция notIn(a, b)

a GLOBAL IN ... - функция globalIn(a, b)

a GLOBAL NOT IN ... - функция globalNotIn(a, b)

a = ANY (subquery) функция in(a, subquery).

a != ANY (subquery) равнозначно a NOT IN (SELECT singleValueOrNull(*) FROM subquery).

a = ALL (subquery) равнозначно a IN (SELECT singleValueOrNull(*) FROM subquery).

a != ALL (subquery) функция notIn(a, subquery).

Примеры

Запрос с ALL:

SELECT number AS a FROM numbers(10) WHERE a > ALL (SELECT number FROM numbers(3, 3));

Результат:

┌─a─┐
│ 6 │
│ 7 │
│ 8 │
│ 9 │
└───┘

Запрос с ANY:

SELECT number AS a FROM numbers(10) WHERE a > ANY (SELECT number FROM numbers(3, 3));

Результат:

┌─a─┐
│ 4 │
│ 5 │
│ 6 │
│ 7 │
│ 8 │
│ 9 │
└───┘

Оператор для работы с датами и временем

EXTRACT

EXTRACT(part FROM date);

Позволяет извлечь отдельные части из переданной даты. Например, можно получить месяц из даты, или минуты из времени.

В параметре part указывается, какой фрагмент даты нужно получить. Доступные значения:

  • DAY — День. Возможные значения: 131.
  • MONTH — Номер месяца. Возможные значения: 112.
  • YEAR — Год.
  • SECOND — Секунда. Возможные значения: 059.
  • MINUTE — Минута. Возможные значения: 059.
  • HOUR — Час. Возможные значения: 023.

Эти значения могут быть указаны также в нижнем регистре (day, month).

В параметре date указывается исходная дата. Поддерживаются типы Date и DateTime.

Примеры:

SELECT EXTRACT(DAY FROM toDate('2017-06-15'));
SELECT EXTRACT(MONTH FROM toDate('2017-06-15'));
SELECT EXTRACT(YEAR FROM toDate('2017-06-15'));

В следующем примере создадим таблицу и добавим в неё значение с типом DateTime.

CREATE TABLE test.Orders
(
    OrderId UInt64,
    OrderName String,
    OrderDate DateTime
)
ENGINE = Log;
INSERT INTO test.Orders VALUES (1, 'Jarlsberg Cheese', toDateTime('2008-10-11 13:23:44'));
SELECT
    toYear(OrderDate) AS OrderYear,
    toMonth(OrderDate) AS OrderMonth,
    toDayOfMonth(OrderDate) AS OrderDay,
    toHour(OrderDate) AS OrderHour,
    toMinute(OrderDate) AS OrderMinute,
    toSecond(OrderDate) AS OrderSecond
FROM test.Orders;
┌─OrderYear─┬─OrderMonth─┬─OrderDay─┬─OrderHour─┬─OrderMinute─┬─OrderSecond─┐
│      2008 │         10 │       11 │        13 │          23 │          44 │
└───────────┴────────────┴──────────┴───────────┴─────────────┴─────────────┘

Больше примеров приведено в тестах.

INTERVAL

Создаёт значение типа Interval которое должно использоваться в арифметических операциях со значениями типов Date и DateTime.

Типы интервалов:

  • SECOND
  • MINUTE
  • HOUR
  • DAY
  • WEEK
  • MONTH
  • QUARTER
  • YEAR

В качестве значения оператора INTERVAL вы можете также использовать строковый литерал. Например, выражение INTERVAL 1 HOUR идентично выражению INTERVAL '1 hour' или INTERVAL '1' hour.

:::danger "Внимание" Интервалы различных типов нельзя объединять. Нельзя использовать выражения вида INTERVAL 4 DAY 1 HOUR. Вместо этого интервалы можно выразить в единицах меньших или равных наименьшей единице интервала, Например, INTERVAL 25 HOUR. Также можно выполнять последовательные операции как показано в примере ниже.

Примеры:

SELECT now() AS current_date_time, current_date_time + INTERVAL 4 DAY + INTERVAL 3 HOUR;
┌───current_date_time─┬─plus(plus(now(), toIntervalDay(4)), toIntervalHour(3))─┐
│ 2020-11-03 22:09:50 │                                    2020-11-08 01:09:50 │
└─────────────────────┴────────────────────────────────────────────────────────┘
SELECT now() AS current_date_time, current_date_time + INTERVAL '4 day' + INTERVAL '3 hour';
┌───current_date_time─┬─plus(plus(now(), toIntervalDay(4)), toIntervalHour(3))─┐
│ 2020-11-03 22:12:10 │                                    2020-11-08 01:12:10 │
└─────────────────────┴────────────────────────────────────────────────────────┘
SELECT now() AS current_date_time, current_date_time + INTERVAL '4' day + INTERVAL '3' hour;
┌───current_date_time─┬─plus(plus(now(), toIntervalDay('4')), toIntervalHour('3'))─┐
│ 2020-11-03 22:33:19 │                                        2020-11-08 01:33:19 │
└─────────────────────┴────────────────────────────────────────────────────────────┘

Вы можете изменить дату, не используя синтаксис INTERVAL, а просто добавив или отняв секунды, минуты и часы. Например, чтобы передвинуть дату на один день вперед, можно прибавить к ней значение 60*60*24.

:::note "Примечание"
Синтаксис `INTERVAL` или функция `addDays` предпочтительнее для работы с датами. Сложение с числом (например, синтаксис `now() + ...`) не учитывает региональные настройки времени, например, переход на летнее время.
:::

Пример:

SELECT toDateTime('2014-10-26 00:00:00', 'Europe/Moscow') AS time, time + 60 * 60 * 24 AS time_plus_24_hours, time + toIntervalDay(1) AS time_plus_1_day;
┌────────────────time─┬──time_plus_24_hours─┬─────time_plus_1_day─┐
│ 2014-10-26 00:00:00 │ 2014-10-26 23:00:00 │ 2014-10-27 00:00:00 │
└─────────────────────┴─────────────────────┴─────────────────────┘

Смотрите также

  • Тип данных Interval
  • Функции преобразования типов toInterval

Оператор логического "И"

Синтаксис SELECT a AND b — вычисляет логическую конъюнкцию между a и b функцией and.

Оператор логического "ИЛИ"

Синтаксис SELECT a OR b — вычисляет логическую дизъюнкцию между a и b функцией or.

Оператор логического отрицания

Синтаксис SELECT NOT a — вычисляет логическое отрицание a функцией not.

Условный оператор

a ? b : c - функция if(a, b, c)

Примечание:

Условный оператор сначала вычисляет значения b и c, затем проверяет выполнение условия a, и только после этого возвращает соответствующее значение. Если в качестве b или с выступает функция arrayJoin(), то размножение каждой строки произойдет вне зависимости от условия а.

Условное выражение

CASE [x]
    WHEN a THEN b
    [WHEN ... THEN ...]
    [ELSE c]
END

В случае указания x - функция transform(x, [a, ...], [b, ...], c). Иначе — multiIf(a, b, ..., c). При отсутствии секции ELSE c, значением по умолчанию будет NULL.

:::note "Примечание"
Функция `transform` не умеет работать с `NULL`.
:::

Оператор склеивания строк

s1 || s2 - функция concat(s1, s2)

Оператор создания лямбда-выражения

x -> expr - функция lambda(x, expr)

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

Оператор создания массива

[x1, ...] - функция array(x1, ...)

Оператор создания кортежа

(x1, x2, ...) - функция tuple(x2, x2, ...)

Ассоциативность

Все бинарные операторы имеют левую ассоциативность. Например, 1 + 2 + 3 преобразуется в plus(plus(1, 2), 3). Иногда это работает не так, как ожидается. Например, SELECT 4 > 3 > 2 выдаст 0.

Для эффективности, реализованы функции and и or, принимающие произвольное количество аргументов. Соответствующие цепочки операторов AND и OR, преобразуются в один вызов этих функций.

Проверка на NULL

ClickHouse поддерживает операторы IS NULL и IS NOT NULL.

IS NULL

  • Для значений типа Nullable оператор IS NULL возвращает:
    • 1, если значение — NULL.
    • 0 в обратном случае.
  • Для прочих значений оператор IS NULL всегда возвращает 0.

Оператор можно оптимизировать, если включить настройку optimize_functions_to_subcolumns. При optimize_functions_to_subcolumns = 1 читается только подстолбец null вместо чтения и обработки данных всего столбца. Запрос SELECT n IS NULL FROM table преобразуется к запросу SELECT n.null FROM TABLE.

SELECT x+100 FROM t_null WHERE y IS NULL
┌─plus(x, 100)─┐
│          101 │
└──────────────┘

IS NOT NULL

  • Для значений типа Nullable оператор IS NOT NULL возвращает:
    • 0, если значение — NULL.
    • 1, в обратном случае.
  • Для прочих значений оператор IS NOT NULL всегда возвращает 1.

Оператор можно оптимизировать, если включить настройку optimize_functions_to_subcolumns. При optimize_functions_to_subcolumns = 1 читается только подстолбец null вместо чтения и обработки данных всего столбца. Запрос SELECT n IS NOT NULL FROM table преобразуется к запросу SELECT NOT n.null FROM TABLE.

SELECT * FROM t_null WHERE y IS NOT NULL
┌─x─┬─y─┐
│ 2 │ 3 │
└───┴───┘