Clickhouse函数介绍

Clickhouse 中至少有2中类型的函数

-正常函数(被称为 functions)和聚合函数.

这两个函数完全不同。正常函数被应用到每行(对于每行,函数的结果不依赖与其他行).聚合函数从不同的行中累计相应的值(例如. 他们依赖整个行的集合). 在本章中,我们将讨论正常函数. 对于聚合函数, 查看章节"Aggregate functions". * 

- 有第三种函数的类型,  'arrayJoin'函数属于; 表函数也能够被单独提及. 

强类型

与标准的 SQL 不同, ClickHouse 有强类型. 换句话说, 它不能在类型之间进行隐式转换. 每个函数可以运行在不同数据类型之上. 这意味着有时你需要使用类型转换函数. 

通用的子表达消除

在一个查询中所有的表达式都有相同的 AST (相同的记录或者相同的语法解析) 能够被考虑有完全相同的值. 这些表达式可以拼接的,一次执行. 相同的子查询也能够按照相同的方式消除. 

结果类型

所有的函数返回一个单值作为结果 (不是多个值,也不是0值). 通常情况下,结果的类型仅通过参数的类型来定义, 不通过值来定义. 异常是 tupleElement 函数 (a.N 操作符), 同时是 toFixedString 函数. 

常量

为了简化, 某些函数的参数仅能带有常数工作. 例如, LIKE 操作符的右侧参数必须是一个常数. 对于常数参数, 几乎所有的函数返回一个常数. 异常是一个函数,可生成随机数. 对于查询来说, ’now' 函数返回不同的值,如果运行在不同的时间点上,但是结果是一个常数, 常数仅在一次查询内是重要的. 一个常数表达式也考虑到一个常数 (例如, LIKE 操作符右侧从多个常量中构建). 函数能够以不同的方式实现,可带有常数和非常数参数. 但是对于一个常数的结果,对于一个仅包含相同值的列应该互相匹配.

不可变性

对于这些参数, 函数不能改变值

-任何的改变作为结果返回. 因此, 计算不同的函数的结果不依赖哪个函数写到了查询中. 

错误处理

一些函数可能抛出一些异常 如果数据是无效的. 在这种情况下, 查询被计算,错误文本将返回给客户端. 对于分布式处理,当一个异常在一个服务器中发生时, 其他服务器也放弃这个查询. 

参数表达式赋值

在大多数编程语言中, 对于某些操作符一个参数可能并不被赋值. 通常情况下,对于操作符  &&, ||, ?:. 但是在 ClickHouse 中, 函数的参数 (操作符) 通常是被赋值的. 这是因为列的整个部分被一次性赋值, 而不是单独计算每个行. 

为分布式查询处理执行函数

对于分布式查询处理, 查询处理的多个阶段尽量执行在远程服务器上, 剩下的阶段被处理在请求服务器上 (合并中间结果和后续处理) . 这意味着函数能够被执行在不同的服务器上. 例如, 在查询中SELECTf(sum(g(x)))FROM distributed_table GROUP BYh(y), 

-如果%%distributed_table%%有至少2个分片,此函数%%g%%和%%h%%在远程服务器上被执行,同时函数%%f%% -在请求服务器上执行. 

- 如果 %%distributed_table%% 仅有一个分片, 所有的函数 %%f%%, %%g%%, 和 %%h%% 在这个分片服务器上执行. 函数的结果通常不依赖于哪个服务器执行. 然而, 优势这个非常重要的. 例如, 函数使用词典, 词典存在于服务器内. 另外一个例子是 %%hostName%% 函数, 返回服务器的名称为了通过服务器进行GROUP BY汇总查询. 如果在查询中一个函数在请求服务器中被执行, 但是你需要在远程服务器上处理, 你能够封装它到任意的聚合函数中或者添加到GROUP BY的一个 Key 中. 

算术函数

对于所有的算术函数, 结果类型被计算作为适合结果的最小数字类型, 如果有这样一个类型. 最小值基于bits位数, 是否它被分配, 是否它是浮点数. 如果没有足够的 bits 位数, 最高的 bit 类型被采纳. 例如:

SELECT toTypeName(0), toTypeName(0+0), toTypeName(0+0+0), toTypeName(0+0+0+0)

┌─toTypeName(0)─┬─toTypeName(plus(0, 0))─┬─toTypeName(plus(plus(0, 0), 0))─┬─toTypeName(plus(plus(plus(0, 0), 0), 0))─┐

│UInt8        │UInt16                │UInt32                          │UInt64                                  │

└───────────────┴────────────────────────┴─────────────────────────────────┴──────────────────────────────────────────┘

算数函数为如下任意类型的服务UInt8,UInt16,UInt32,UInt64,Int8,Int16,Int32,Int64,Float32,or Float64。Overflow以C++的方式被生成。

plus(a,b),a + b 操作符

计算数字的总和。你也可以添加带有Date或DateTime的整个数字。对于 Date 类型,添加一个整个数字意味着添加对应的天数。意味着添加对应的秒数。

minus(a,b),a - b 操作符

计算不同.此结果通常是signed.你也能够从date或datetime类型上计算整个数字.想法是相同的-查看以上的'plus'. 

multiply(a,b),a * b 操作符

计算数字相乘. 

divide(a,b),a / b 操作符

计算数字相除. 结果类型经常是一个浮点类型. 不是整数相除. 对于整数相除, 使用 'intDiv' 函数. 当除以0时,结果为 'inf', '-inf', 或者'nan'. 

intDiv(a,b)

计算商数. 除以整数, 四舍五入(通过绝对值). 当除以0或最小负整数时,抛出异常. 

计算数字的商。

intDivOrZero(a,b)

不同于 'intDiv' ,它将返回0,当除以0或当除以一个最小负整数时. 

modulo(a,b),a % b操作符 

在相除之后计算剩余数. 如果参数是浮点数, 它们先转换为整数,通过去除浮点精度部分. 剩余数与C++处理方式相同. 截断相除用于负数. 一个异常将要抛出,当除以0或者当除以最小负数. 

negate(a),-a 操作符

计算一个带有反符号的数字. 结果经常带有符号. 

abs(a)操作符

计算一个数的绝对值'a'.  如果 a< 0, 它将返回 -a. 对于非符号类型, 什么都不做. 对于符号整型类型, 将返回非符号数字. 

gcd(a, b)操作符

返回数字最通用的除数. 当除以0或当除以最小负数后,异常将抛出.

lcm(a, b)

返回最通用的乘数. 当除以0或当除以最小负数后,异常将抛出.

Bit 函数

Bit函数服务于UInt8,UInt16,UInt32,UInt64,Int8,Int16,Int32,Int64,Float32,或者Float64.结果类型是一个带有位数的整型,与参数的最大位数相等.如果至少有一个参数被指定,结果将是一个符号化数字.如果一个参数是一个浮点数,它将转换到Int64. 

为数组服务的函数

empty

为空数组返回1,对于非空数组返回0。结果类型是UInt8。该函数也适用于字符串。

notEmpty

对于空数组返回0,对于非空数组返回1。结果类型是UInt8。该函数也适用于字符串。

length

返回数组中的项目数。结果类型是UInt64。该函数也适用于字符串。

emptyArrayUInt8, emptyArrayUInt16, emptyArrayUInt32, emptyArrayUInt64

emptyArrayInt8, emptyArrayInt16, emptyArrayInt32, emptyArrayInt64

emptyArrayFloat32, emptyArrayFloat64

emptyArrayDate, emptyArrayDateTime

emptyArrayString

接受零参数并返回相应类型的空数组。

emptyArrayToSingle

接受一个空数组并返回一个等于默认值的一个元素的数组。

range(N)

返回从0到N-1的数字数组。以防万一,如果在数据块中创建总长度超过100,000,000个元素的数组,则会引发异常。

array(x1, ...), оператор [x1, ...]

从函数参数创建一个数组。参数必须是常量,并且具有最小通用类型的类型。必须至少传递一个参数,否则不清楚创建哪种类型的数组。也就是说,你不能使用这个函数来创建一个空数组(为此,使用上面描述的'emptyArray *'函数)。返回一个“Array(T)”类型结果,其中“T”是传递参数中最小的通用类型。

arrayConcat

绑定作为参数传递的数组.

arrayConcat(arrays)

Arguments

arrays – 逗号分隔的数组[值].

Example

SELEC TarrayConcat([1,2],[3,4],[5,6]) AS res

┌─res───────────┐│ [1,2,3,4,5,6] │└───────────────┘

arrayElement(arr, n), 操作符 arr[n]

从数组'arr'中获取索引为'n'的元素。'n'必须是任何整数类型。数组中的索引从1开始。支持负数索引。在这种情况下,它从末尾选择相应的元素。例如,'arr [-1]'是数组中的最后一项。

如果索引落在数组边界之外,它将返回一些默认值(数字为0,字符串为空字符串等)。

has(arr, elem)

检查'arr'数组是否有'elem'元素。如果元素不在数组中,则返回0;如果在数组中,则返回1。

indexOf(arr, x)

如果它在数组中,则返回“x”元素的索引(从1开始);如果不在数组中,则返回0。

countEqual(arr, x)

返回数组中的等于 x 的元素数量. 等于 arrayCount (elem->elem = x, arr).

arrayEnumerate(arr)

返回数组 [1, 2, 3, ..., length (arr) ]

函数通常被用于ARRAY JOIN。它允许为每个数组计算 count,在使用ARRAY JOIN后。例如:

SELECT count() AS Reaches,countIf(num=1) AS Hits FROM test.hits ARRAY JOIN GoalsReached,array Enumerate(GoalsReached) AS num WHERE CounterID=160656 LIMIT 10

┌─Reaches─┬──Hits─┐

│  95606 │ 31406 │

└─────────┴───────┘

在这个例子中,Reaches是转换次数(应用ARRAY JOIN后收到的字符串),Hits是页面浏览量(ARRAY JOIN之前的字符串)。在这种情况下,您可以通过更简单的方式获得相同的结果:

SELECT sum(length(GoalsReached)) AS Reaches, count() AS Hits FROM test.hits WHERE(CounterID=160656) AND notEmpty(GoalsReached)

┌─Reaches─┬──Hits─┐

│  95606 │ 31406 │

└─────────┴───────┘

该功能也可用于高阶功能。例如,您可以使用它来获取匹配条件的元素的数组索引。

arrayEnumerateUniq(arr, ...)

返回与源数组大小相同的数组,为每个元素指示其位置在具有相同值的元素中的位置。例如:arrayEnumerateUniq([10,20,10,30])= [1,1,2,1]。

使用ARRAY JOIN和数组元素聚合时,此函数很有用。例:

SELECT Goals.IDASGoalID, sum(Sign)ASReaches, sumIf(Sign,num=1) AS Visits  FROM test.visits ARRAYJOIN Goals, arrayEnumerateUniq(Goals.ID) AS num WHERE CounterID = 160656 GROUP BY GoalID ORDERBY Reaches DESC LIMIT 10

┌──GoalID─┬─Reaches─┬─Visits─┐

│  53225 │    3214 │  1097 │

│ 2825062 │    3188 │  1097 │

│  56600 │    2803 │    488 │

│ 1989037 │    2401 │    365 │

│ 2830064 │    2396 │    910 │

│ 1113562 │    2372 │    373 │

│ 3270895 │    2262 │    812 │

│ 1084657 │    2262 │    345 │

│  56599 │    2260 │    799 │

│ 3271094 │    2256 │    812 │

└─────────┴─────────┴────────┘

在这个例子中,每个目标ID都有一个转换次数的计算(目标嵌套数据结构中的每个元素都是达到的目标,我们称之为转换)以及会话数量。如果没有ARRAY JOIN,我们可以将会话的数量计算为总和(Sign)。但是在这种特殊情况下,行被嵌套的Goals结构乘以,所以为了在此之后计算每个会话一次,我们将一个条件应用到arrayEnumerateUniq(Goals.ID)函数的值。

arrayEnumerateUniq函数可以将多个大小相同的数组作为参数。在这种情况下,唯一性被考虑为所有数组中相同位置元素的元组。

SELECT array EnumerateUniq([1,1,1,2,2,2],[1,1,2,1,1,2]) AS res

┌─res───────────┐

│ [1,2,1,1,2,1] │

└───────────────┘

当使用ARRAY JOIN和嵌套的数据结构,并在这个结构中的多个元素之间进一步聚合时,这是必要的。

arrayPopBack

删除数组中的最后一项。

arrayPopBack(array)

参数

array – 数组.

例如

SELECT arrayPopBack([1,2,3]) AS res

┌─res───┐

│ [1,2] │

└───────┘

arrayPopFront

从数组中删除第一个元素

arrayPopFront(array)

参数

array – 数组.

示例

SELECT arrayPopFront([1,2,3]) AS res

┌─res───┐

│ [2,3] │

└───────┘

arrayPushBack

在数组的结尾添加一个元素

array PushBack(array,single_value)

参数

array – 数组.

single_value - 单个值。只有数字可以添加到数组中,只有将字符串添加到字符串数组中。在添加数字时,ClickHouse会自动为数组的数据类型设置single_value类型。有关ClickHouse中数据类型的更多信息,请参阅“数据类型”。

示例

SELECT arrayPushBack(['a'],'b') AS res

┌─res───────┐

│ ['a','b'] │

└───────────┘

arrayPushFront

在数组的开头添加一个元素

array PushFront(array,single_value)

array – 数组.

single_value - 单个值。只有数字可以添加到数组中,只有将字符串添加到字符串数组中。在添加数字时,ClickHouse会自动为数组的数据类型设置single_value类型。有关ClickHouse中数据类型的更多信息,请参阅“数据类型”。

示例

SELECT array PushBack(['b'],'a') AS res

┌─res───────┐

│ ['a','b'] │

└───────────┘

arraySlice

返回数组的切片.

arraySlice(array,offset[,length])

参数

array – 数组数据.

偏移量 - 从数组的边界偏移。正值表示左侧的偏移量,负值表示右侧的缩进量。数组项的编号从1开始。

长度 - 所需切片的长度。如果你指定一个负值,函数返回一个开放的片段[offset,array_length - length)。如果省略该值,则函数返回切片[offset,the_end_of_array]。

示例

SELECT arraySlice([1,2,3,4,5],2,3) AS res

┌─res─────┐

│ [2,3,4] │

└─────────┘

arrayUniq(arr, ...)

如果传递一个参数,它会计算数组中不同元素的数量。如果传递多个参数,它将计算多个数组中相应位置的元素的不同元组的数量。

如果你想得到一个数组中唯一元素的列表,你可以使用arrayReduce('groupUniqArray',arr)。

arrayJoin(arr)

一个特殊的函数. 请查看章节 "ArrayJoin function".

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,116评论 0 13
  • 按照计划,昨天下午给大我一岁的表哥,打了电话,开始了40分钟的讨论与激励。 谈话中他的情况可以总结为三点。 一是自...
    Inker阅读 186评论 0 1
  • 微信开发 - 杂项笔记 引言 此篇用来记录微信开发的一些操作和问题,便于以后当做为文档翻阅 为阅读原文的链接,添加...
    Wenliang阅读 372评论 0 2
  • Avro总结(RPC/序列化) Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。 它的主要特点有:...
    Albert陈凯阅读 42,516评论 1 14
  • extern 修饰外部变量和外部函数,auto是修饰自带变量,就是堆栈区最常用的。
    林步蜓阅读 607评论 0 0