跳至主要内容

Tuple(T1, T2, ...)

一个元组,每个元素都有一个单独的 类型。元组必须包含至少一个元素。

元组用于临时列分组。当查询中使用 IN 表达式时,以及为指定 lambda 函数的某些形式参数时,可以对列进行分组。有关详细信息,请参阅部分 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; -- by name
SELECT a.2 FROM named_tuples; -- by index

结果

┌─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─┐
20221231
200011
└──────┴───────┴─────┘

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

┌─year─┬─month─┬─day─┐
20221231
└──────┴───────┴─────┘


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─┐
14266.5
14270
2110
220
└─────┴──────────┴───────┘

-- Let's find a value for each key with the biggest duration, if durations are equal, select the biggest value

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))─┐
14270
220
└─────┴───────────────┴───────────────────────────────────────┘