最近接触了clickhouse,不得不说性能是真的强大,即使最简单的使用,不加任何优化也比常规数据库要快上很多,所以一直把它当作普通数据库来用,也支持sql语句,上手起来很快,不过今天写需求时用到了case when语句,从而引出了clickhouse字段别名的一些用法。
首先说一下别名指的是:select columnA as columnB 这种用法。
(得出的结论均为自己摸索,未查到相关资料,如有错误多多指正)
最大不同:上一个字段的别名可在下面的字段中直接使用
这个是接触ck时最不习惯的问题,因为以前接触过的数据库没有过这种用法,所以在使用ck时遇到了很多错误。举例:
mysql数据库
mysql> select 1 as a ,a +1 as b;
ERROR 1054 (42S22): Unknown column 'a' in 'field list'
一个简单的查询,但是会报错,即上一个字段的别名是不能在接下来被识别的。
clickhouse:
SELECT
1 AS a,
a + 1 AS b
┌─a─┬─b─┐
│ 1 │ 2 │
└───┴───┘
1 rows in set. Elapsed: 0.004 sec.
但是在ck里,它是可以被识别的!!! 但是也会导致下面的字段中都会被强制替换。意思就如果表中原来有一个字段名是 “num” ,对其进行sum求和后,还是取了原来一样的别名 即:sum(num) as num
那接下来的字段是识别不到原来的num的,说的有点啰嗦,直接上测试:
建测试表:
CREATE TABLE test123
ENGINE = TinyLog() AS
SELECT
'a' AS name,
1 AS num
UNION ALL
SELECT
'a' AS name,
2 AS num
UNION ALL
SELECT
'a' AS name,
3 AS num
UNION ALL
SELECT
'b' AS name,
4 AS num
:) select * from test123 ;
┌─name─┬─num─┐
│ a │ 3 │
│ b │ 4 │
│ a │ 1 │
│ a │ 2 │
└──────┴─────┘
4 rows in set. Elapsed: 0.004 sec.
测试语句:
SELECT
sum(num) AS num,
sum(num + 1) AS num_1
FROM test123;
Received exception from server (version 20.12.3):
Code: 184. DB::Exception: Received from 10.***.***.***:9000. DB::Exception: Aggregate function sum(num) is found inside another aggregate function in query: While processing sum(num) AS num.
0 rows in set. Elapsed: 0.004 sec.
可以看到,这种写法在ck中会报错 Aggregate function sum(num) is found inside another aggregate,但是传统数据库是支持这种写法的,开始的时候不知道这个特性,
还以为是聚合函数的问题,看了半天聚合函数的文档。
但是一旦发现这个特性之后就会觉得它很实用!比如求占比的时候可以直接用算好的结果:
而且虽然和传统数据库不一样,不过规避它的方式也很简单,只要取的别名不和原来字段名一样就好了。
SELECT
sum(num) AS num1,
sum(num + 1) AS num_1
FROM test123
┌─num1─┬─num_1─┐
│ 10 │ 14 │
└──────┴───────┘
1 rows in set. Elapsed: 0.004 sec.
但是很多时候为了美观(偷懒),就不想取新的名字,大多数时候也是没什么影响的,不过今天就遇到了问题,就是这个别名的识别不仅作用在select语句中,甚至
还作用在where语句中!
SELECT if(num > 1, '大于1', '小于1') AS num
FROM test123
WHERE num > 1
Received exception from server (version 20.12.3):
Code: 386. DB::Exception: Received from 10.***.***.***:9000. DB::Exception: There is no supertype for types String, UInt8 because some of them are String/FixedString and some of them are not: while executing 'FUNCTION greater(if(greater(num, 1), '大于1', '小于1') : 5, 1 : 1) -> greater(if(greater(num, 1), '大于1', '小于1'), 1) UInt8 : 6'.
0 rows in set. Elapsed: 0.004 sec.
就这么一个简单的类型错误:There is no supertype for types String, UInt8 because some of them are String/FixedString and some of them are not: while executing,排查了半天(当然也是遇到的错误的语句要比这个复杂,涉及到了case when的时间判断等,甚至在写这篇博客的时候我还以为是case when的问题。。。)
这么一来相当于直接顶替了传统数据库中having 的用法,所以各位如果也遇到了以上错误,可以注意下别名的问题,是不是有类似用法。