Кортеж элементов, каждый из которых имеет свой отдельный тип. Кортеж должен содержать как минимум один элемент.
Кортежи используются для временной группировки колонок. Колонки могут быть сгруппированы, когда в запросе используется выражение IN, а также для указания определенных формальных параметров функций-лямбд. Для получения дополнительной информации смотрите разделы Операторы IN и Функции высшего порядка.
Кортежи могут быть результатом запроса. В этом случае, для текстовых форматов, отличных от JSON, значения разделены запятыми в скобках. В форматах JSON кортежи выводятся как массивы (в квадратных скобках).
Создание Кортежей
Вы можете использовать функцию для создания кортежа:
Пример создания кортежа:
SELECT tuple(1, 'a') AS x, toTypeName(x)
┌─x───────┬─toTypeName(tuple(1, 'a'))─┐
│ (1,'a') │ Tuple(UInt8, String) │
└─────────┴───────────────────────────┘
Кортеж может содержать один элемент
Пример:
┌─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 │
└─────┴───────────────┴───────────────────────────────────────┘