1. 介绍 ClickHouse 的操作符
所有的操作符(运算符)都会在查询时,依据他们的优先级及其结合顺序,在被解析时转换为对应的函数。
下面按优先级从高到低列出各组运算符及其对应的函数:
2. 下标运算符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
select array(1,2,3) as a, a[1] as a1,arrayElement(a, 1) as func_a1; ┌─a───────┬─a1─┬─func_a1─┐ │ [1,2,3] │ 1 │ 1 │ └─────────┴────┴─────────┘
select tuple(1,'a') as a, a.1 as a1,tupleElement(a, 2) as func_a1 ┌─a───────┬─a1─┬─func_a1─┐ │ (1,'a') │ 1 │ a │ └─────────┴────┴─────────┘
|
3. 负号
1 2 3 4 5 6
|
select -(-3) as n1,negate(n1) as n2; ┌─n1─┬─n2─┐ │ 3 │ -3 │ └────┴────┘
|
4. 乘、除、取余、加、减、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
select 5 * 5 as n1,multiply(n1, 5) as n2; ┌─n1─┬──n2─┐ │ 25 │ 125 │ └────┴─────┘
select 5 / 5 as n1,divide(n1, 5) as n2; ┌─n1─┬──n2─┐ │ 1 │ 0.2 │ └────┴─────┘
select 8 % 5 as n1, modulo(n1, 2) as n2; ┌─n1─┬─n2─┐ │ 3 │ 1 │ └────┴────┘
select 5 + 5 as n1, plus(n1, 5) as n2; ┌─n1─┬─n2─┐ │ 10 │ 15 │ └────┴────┘
select 10 - 5 as n1, minus(n1, 5) as n2; ┌─n1─┬─n2─┐ │ 5 │ 0 │ └────┴────┘
|
5. 关系运算符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
select 'a' = 'b' as n1,'a' == 'b' as n2, equals('a','a') as n3,toTypeName(n1) as type; ┌─n1─┬─n2─┬─n3─┬─type──┐ │ 0 │ 0 │ 1 │ UInt8 │ └────┴────┴────┴───────┘
select 'a' != 'b' as n1,'a' <> 'b' as n2, notEquals('a','a') as n3,toTypeName(n1) as type; ┌─n1─┬─n2─┬─n3─┬─type──┐ │ 1 │ 1 │ 0 │ UInt8 │ └────┴────┴────┴───────┘
select 'a' <= 'b' as n1, lessOrEquals('a','a') as n2,toTypeName(n1) as type; ┌─n1─┬─n2─┬─type──┐ │ 1 │ 1 │ UInt8 │ └────┴────┴───────┘
select 'a' >= 'b' as n1, lessOrEquals('a','a') as n2,toTypeName(n1) as type;
select 'a' < 'b' as n1, less('a','a') as n2,toTypeName(n1) as type; ┌─n1─┬─n2─┬─type──┐ │ 1 │ 0 │ UInt8 │ └────┴────┴───────┘
select 'a' > 'b' as n1, greater('a','a') as n2,toTypeName(n1) as type; ┌─n1─┬─n2─┬─type──┐ │ 0 │ 0 │ UInt8 │ └────┴────┴───────┘
select 's1' like 's2' as n1, like('s1','s1') as n2; ┌─n1─┬─n2─┐ │ 0 │ 1 │ └────┴────┘
select 's1' not like 's2' as n1, notLike('s1','s1') as n2; ┌─n1─┬─n2─┐ │ 1 │ 0 │ └────┴────┘
SELECT ('b' >= 'a') AND ('b' <= 'c') AS n1, ('b' <= 'a') AND ('b' >= 'c') AS n2;
┌─n1─┬─n2─┐ │ 1 │ 0 │ └────┴────┘
|
6. 集合关系运算符
1 2 3 4
| a IN ... – 对应函数 in(a, b) a NOT IN ... – 对应函数 notIn(a, b) a GLOBAL IN ... – 对应函数 globalIn(a, b) a GLOBAL NOT IN ... – 对应函数 globalNotIn(a, b)
|
7. 逻辑非或非
1 2 3 4 5 6 7 8 9 10 11 12 13
|
select 'a'='a' and 'b'='b' as n1,and('a'='b','b'='c') as n2; ┌─n1─┬─n2─┐ │ 1 │ 0 │ └────┴────┘
select 'a'='a' or 'b'='b' as n1,or('a'='b','c'='c') as n2; ┌─n1─┬─n2─┐ │ 1 │ 1 │ └────┴────┘
|
8. 条件运算符
1 2 3 4 5 6
|
select 1 < 2 ? 'yes' : 'no' as s1, if(1 > 2 ,'no','yes') as s2; ┌─s1──┬─s2──┐ │ yes │ yes │ └─────┴─────┘
|
9. 日期时间运算符
1 2 3 4 5 6 7 8 9 10 11 12 13
|
EXTRACT(part FROM date);
YEAR — 获取年 QUARTER - 获取季度,1(一季度:1-3),2(二季度:4-6),3(三季度:7-9),4(四季度:10-12) MONTH — 获取月份 1–12. DAY — 获取日 1–31. HOUR — 获取小时 0–23. MINUTE — 获取分钟 0–59. SECOND — 获取秒钟 0–59.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
SELECT toDate('2021-08-05 21:50:25') as dt , EXTRACT(YEAR FROM dt) as d1,toYear(dt) as d2; ┌─────────dt─┬───d1─┬───d2─┐ │ 2021-08-05 │ 2021 │ 2021 │ └────────────┴──────┴──────┘
SELECT toDate('2021-08-05 21:50:25') as dt , EXTRACT(QUARTER FROM dt) as d1, toQuarter(dt) as d2; ┌─────────dt─┬─d1─┬─d2─┐ │ 2021-08-05 │ 3 │ 3 │ └────────────┴────┴────┘
SELECT toDate('2021-08-05 21:50:25') as dt , EXTRACT(MONTH FROM dt) as d1,toMonth(dt) as d2; ┌─────────dt─┬─d1─┬─d2─┐ │ 2021-08-05 │ 8 │ 8 │ └────────────┴────┴────┘
SELECT toDate('2021-08-05 21:50:25') as dt , EXTRACT(DAY FROM dt) as d1,toDayOfMonth(dt) as d2; ┌─────────dt─┬─d1─┬─d2─┐ │ 2021-08-05 │ 5 │ 5 │ └────────────┴────┴────┘
SELECT toDateTime('2021-08-05 21:50:25') as dt ,EXTRACT(HOUR FROM dt) as d1, toHour(dt) as d2; ┌──────────────────dt─┬─d1─┬─d2─┐ │ 2021-08-05 21:50:25 │ 21 │ 21 │ └─────────────────────┴────┴────┘
SELECT toDateTime('2021-08-05 21:50:25') as dt , EXTRACT(MINUTE FROM dt) as d1,toMinute(dt) as d2; ┌──────────────────dt─┬─d1─┬─d2─┐ │ 2021-08-05 21:50:25 │ 50 │ 50 │ └─────────────────────┴────┴────┘
SELECT toDateTime('2021-08-05 21:50:25') as dt , EXTRACT(SECOND FROM dt) as d1,toSecond(dt) as d2; ┌──────────────────dt─┬─d1─┬─d2─┐ │ 2021-08-05 21:50:25 │ 25 │ 25 │ └─────────────────────┴────┴────┘
|
9.2. INTERVAL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
select toDate('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 YEAR as d1,addYears(dt,1) d2; ┌─────────dt─┬─────────d1─┬─────────d2─┐ │ 2021-08-05 │ 2022-08-05 │ 2022-08-05 │ └────────────┴────────────┴────────────┘
select toDate('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 QUARTER as d1,addQuarters(dt,1) d2; ┌─────────dt─┬─────────d1─┬─────────d2─┐ │ 2021-08-05 │ 2021-11-05 │ 2021-11-05 │ └────────────┴────────────┴────────────┘
select toDate('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 MONTH as d1,addMonths(dt,1) d2; ┌─────────dt─┬─────────d1─┬─────────d2─┐ │ 2021-08-05 │ 2021-09-05 │ 2021-09-05 │ └────────────┴────────────┴────────────┘
select toDate('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 WEEk as d1,addWeeks(dt,1) d2; ┌─────────dt─┬─────────d1─┬─────────d2─┐ │ 2021-08-05 │ 2021-08-12 │ 2021-08-12 │ └────────────┴────────────┴────────────┘
select toDate('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 DAY as d1,addDays(dt,1) d2; ┌─────────dt─┬─────────d1─┬─────────d2─┐ │ 2021-08-05 │ 2021-08-06 │ 2021-08-06 │ └────────────┴────────────┴────────────┘
select toDateTime('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 HOUR as d1,addHours(dt,1) d2; ┌──────────────────dt─┬──────────────────d1─┬──────────────────d2─┐ │ 2021-08-05 21:50:25 │ 2021-08-05 22:50:25 │ 2021-08-05 22:50:25 │ └─────────────────────┴─────────────────────┴─────────────────────┘
select toDateTime('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 MINUTE as d1,addMinutes(dt,1) d2; ┌──────────────────dt─┬──────────────────d1─┬──────────────────d2─┐ │ 2021-08-05 21:50:25 │ 2021-08-05 21:51:25 │ 2021-08-05 21:51:25 │ └─────────────────────┴─────────────────────┴─────────────────────┘
select toDateTime('2021-08-05 21:50:25') as dt, dt + INTERVAL 1 SECOND as d1,addSeconds(dt,1) d2; ┌──────────────────dt─┬──────────────────d1─┬──────────────────d2─┐ │ 2021-08-05 21:50:25 │ 2021-08-05 21:50:26 │ 2021-08-05 21:50:26 │ └─────────────────────┴─────────────────────┴─────────────────────┘
|
10. CASE条件表达式
1 2 3 4 5
| CASE [x] WHEN a THEN b [WHEN ... THEN ...] [ELSE c] END
|
如果指定了 x ,该表达式会转换为 transform(x, [a, …], [b, …], c) 函数。否则转换为
multiIf(a, b, …, c)
如果该表达式中没有 ELSE c 子句,则默认值就是 NULL
但 transform 函数不支持 NULL
11. 连接运算符
1 2 3 4 5 6 7
|
select 'hello ' || 'world' as s1, concat('hello ','world') as s2; ┌─s1──────────┬─s2──────────┐ │ hello world │ hello world │ └─────────────┴─────────────┘
|
12. 创建 Lambda 函数
1 2 3 4 5 6 7
|
SELECT arraySort((x) -> x, [5,4,3,1,2,3]) as res; ┌─res───────────┐ │ [1,2,3,3,4,5] │ └───────────────┘
|
13. 创建数组
1 2 3 4 5 6
|
select [1,1,3] as a1,array(1,2,3) as a2,toTypeName(a1) as type; ┌─a1──────┬─a2──────┬─type─────────┐ │ [1,1,3] │ [1,2,3] │ Array(UInt8) │ └─────────┴─────────┴──────────────┘
|
14. 创建元组
1 2 3 4 5 6
|
select (1,'b',3.2) as t1,tuple(1,'a',0.1) as t2,toTypeName(t1) as type; ┌─t1──────────┬─t2──────────┬─type──────────────────────────┐ │ (1,'b',3.2) │ (1,'a',0.1) │ Tuple(UInt8, String, Float64) │ └─────────────┴─────────────┴───────────────────────────────┘
|
15. 结合方式
所有的同级操作符从左到右结合。例如, 1 + 2 + 3 会转换成 plus(plus(1, 2), 3)。
所以,有时他们会跟我们预期的不太一样。例如, SELECT 4 > 2 > 3 的结果是0。
为了高效, and 和 or 函数支持任意多参数,一连串的 AND 和 OR 运算符会转换成其对应的单个函数。
1 2 3 4 5 6 7 8 9
| select 1 + 2 + 3; ┌─plus(plus(1, 2), 3)─┐ │ 6 │ └─────────────────────┘
SELECT 4 > 2 > 3; ┌─greater(greater(4, 2), 3)─┐ │ 0 │ └───────────────────────────┘
|
16. 判断是否为NULL
ClickHouse 支持 IS NULL 和 IS NOT NULL
16.1. IS NULL
- 值为 NULL 返回 1(true)
- 值不为 NULL 返回 0(false)
1 2 3 4 5 6 7
| select * from ( select 'null is true' as s1, NULL as n1, isNull(n1) as isn ) t where n1 is NULL; ┌─s1───────────┬─n1───┬─isn─┐ │ null is true │ ᴺᵁᴸᴸ │ 1 │ └──────────────┴──────┴─────┘
|
16.2. IS NOT NULL
- 值不为 NULL 返回 1(true)
- 值为 NULL 返回 0(false)
1 2 3 4 5 6
| select * from ( select 'null is true' as s1, NULL as n1, 'hello' as n2, isNotNull(n2) as isn ) t where n2 is NOT NULL; ┌─s1───────────┬─n1───┬─n2────┬─isn─┐ │ null is true │ ᴺᵁᴸᴸ │ hello │ 1 │ └──────────────┴──────┴───────┴─────┘
|