Перейти к основному содержимому
Перейти к основному содержимому

Tuple(T1, T2, ...)

Кортеж элементов, каждый из которых имеет свой отдельный тип. Кортеж должен содержать как минимум один элемент.

Кортежи используются для временной группировки колонок. Колонки могут быть сгруппированы, когда в запросе используется выражение IN, а также для указания определенных формальных параметров функций-лямбд. Для получения дополнительной информации смотрите разделы Операторы IN и Функции высшего порядка.

Кортежи могут быть результатом запроса. В этом случае, для текстовых форматов, отличных от JSON, значения разделены запятыми в скобках. В форматах JSON кортежи выводятся как массивы (в квадратных скобках).

Создание Кортежей

Вы можете использовать функцию для создания кортежа:

tuple(T1, T2, ...)

Пример создания кортежа:

SELECT tuple(1, 'a') AS x, toTypeName(x)
┌─x───────┬─toTypeName(tuple(1, 'a'))─┐
│ (1,'a') │ Tuple(UInt8, String)      │
└─────────┴───────────────────────────┘

Кортеж может содержать один элемент

Пример:

SELECT tuple('a') AS x;
┌─x─────┐
│ ('a') │
└───────┘

Синтаксис (tuple_element1, tuple_element2) может быть использован для создания кортежа из нескольких элементов без вызова функции tuple().

Пример:

SELECT (1, 'a') AS x, (today(), rand(), 'someString') AS y, ('a') AS not_a_tuple;
┌─x───────┬─y──────────────────────────────────────┬─not_a_tuple─┐
│ (1,'a') │ ('2022-09-21',2006973416,'someString') │ a           │
└─────────┴────────────────────────────────────────┴─────────────┘

Обнаружение типа данных

При создании кортежей на лету, ClickHouse интерпретирует тип аргументов кортежа как наименьшие типы, которые могут содержать предоставленное значение аргумента. Если значение является NULL, интерпретируемый тип — Nullable.

Пример автоматического обнаружения типа данных:

SELECT tuple(1, NULL) AS x, toTypeName(x)
┌─x─────────┬─toTypeName(tuple(1, NULL))──────┐
│ (1, NULL) │ Tuple(UInt8, Nullable(Nothing)) │
└───────────┴─────────────────────────────────┘

Ссылка на элементы Кортежа

Элементы кортежа могут быть упомянуты по имени или по индексу:

CREATE TABLE named_tuples (`a` Tuple(s String, i Int64)) ENGINE = Memory;
INSERT INTO named_tuples VALUES (('y', 10)), (('x',-10));

SELECT a.s FROM named_tuples; -- по имени
SELECT a.2 FROM named_tuples; -- по индексу

Результат:

┌─a.s─┐
│ y   │
│ x   │
└─────┘

┌─tupleElement(a, 2)─┐
│                 10 │
│                -10 │
└────────────────────┘

Операции сравнения с Кортежем

Два кортежа сравниваются, последовательно сравнивая их элементы слева направо. Если элемент первого кортежа больше (меньше) соответствующего элемента второго кортежа, то первый кортеж больше (меньше) второго, в противном случае (если оба элемента равны) сравнивается следующий элемент.

Пример:

SELECT (1, 'z') > (1, 'a') c1, (2022, 01, 02) > (2023, 04, 02) c2, (1,2,3) = (3,2,1) c3;
┌─c1─┬─c2─┬─c3─┐
│  1 │  0 │  0 │
└────┴────┴────┘

Примеры из реальной жизни:

CREATE TABLE test
(
    `year` Int16,
    `month` Int8,
    `day` Int8
)
ENGINE = Memory AS
SELECT *
FROM values((2022, 12, 31), (2000, 1, 1));

SELECT * FROM test;

┌─year─┬─month─┬─day─┐
│ 2022 │    12 │  31 │
│ 2000 │     1 │   1 │
└──────┴───────┴─────┘

SELECT *
FROM test
WHERE (year, month, day) > (2010, 1, 1);

┌─year─┬─month─┬─day─┐
│ 2022 │    12 │  31 │
└──────┴───────┴─────┘


CREATE TABLE test
(
    `key` Int64,
    `duration` UInt32,
    `value` Float64
)
ENGINE = Memory AS
SELECT *
FROM values((1, 42, 66.5), (1, 42, 70), (2, 1, 10), (2, 2, 0));

SELECT * FROM test;

┌─key─┬─duration─┬─value─┐
│   1 │       42 │  66.5 │
│   1 │       42 │    70 │
│   2 │        1 │    10 │
│   2 │        2 │     0 │
└─────┴──────────┴───────┘

-- Найдем значение для каждого ключа с наибольшей длительностью, если длительности равны, выберем наибольшее значение

SELECT
    key,
    max(duration),
    argMax(value, (duration, value))
FROM test
GROUP BY key
ORDER BY key ASC;

┌─key─┬─max(duration)─┬─argMax(value, tuple(duration, value))─┐
│   1 │            42 │                                    70 │
│   2 │             2 │                                     0 │
└─────┴───────────────┴───────────────────────────────────────┘