# ClickHouse函数
[TOC]
## 高阶函数
高阶函数、`->`运算符和 lambda(params, expr) 函数
https://clickhouse.tech/docs/en/sql-reference/functions/
高阶函数只能接受 lambda 函数作为它们的函数参数。要将 lambda 函数传递给高阶函数,请使用`->`运算符。箭头左侧有一个形参,它是任意 ID,或多个形参——元组中的任意 ID。箭头右侧有一个表达式,可以使用这些形式参数,以及任何表格列。
例子:
~~~
x -> 2 * x
str -> str != Referer
~~~
接受多个参数的 lambda 函数也可以传递给高阶函数。在这种情况下,高阶函数会传递几个长度相同的数组,这些数组将对应于这些参数。
对于某些函数,可以省略第一个参数(lambda 函数)。在这种情况下,假定映射相同。
## 数组函数
文档:https://clickhouse.tech/docs/en/sql-reference/functions/array-functions/
- arrayConcat

- arrayElement(arr,n)

- has(arr,elem)
检查’arr’数组是否具有’elem’元素。
如果元素不在数组中,则返回0;如果在,则返回1。

- indexOf(arr, x)
如果它在数组中,则返回第一个 'x' 元素的索引(从 1 开始),否则返回 0。

- arrayCount(高阶函数)
返回 arr 数组中 func 返回非 0 的元素数。如果未指定 'func',则返回数组中非零元素的数量。

- countEqual(arr, x)
返回数组中等于 x 的元素数。

- arrayEnumerateUniq(arr, ...)
返回一个与源数组大小相同的数组,指示每个元素在具有相同值的元素中的次数
此函数在使用 ARRAY JOIN 和数组元素聚合时很有用。

- arrayPopBack
从数组中删除最后一项

- arrayDistinct
数组去重

- arrayFilter(func, arr1, …)(高阶函数)
返回func过滤的元素

- arrayMap(func, arr1, ...)(高阶函数)
返回从`func`函数的原始应用中获得的数组到`arr`数组中的每个元素。

- arrayJoin(arr)

## 类型转换
文档:https://clickhouse.tech/docs/en/sql-reference/functions/type-conversion-functions/
- toInt(8|16|32|64|128|256)
将输入值转换为数据类型。
~~~
SELECT toInt64(nan), toInt32(32), toInt16('16'), toInt8(8.8);
~~~
- toInt(8|16|32|64|128|256)OrZero
失败返回0
~~~
SELECT toInt64OrZero('123123'), toInt8OrZero('123qwe123');
~~~
- toInt(8|16|32|64|128|256)OrNull
失败返回null
~~~
SELECT toInt64OrNull('123123'), toInt8OrNull('123qwe123');
~~~
- toString
转换为字符串或从字符串转换时,来格式化或解析值。
- CAST(x, T)
将’x’转换为’t’数据类型。还支持语法CAST(x AS t)
## 字符串函数
文档:https://clickhouse.tech/docs/en/sql-reference/functions/string-functions/
- empty
- notEmpty
- length
- splitByChar
返回拆分后的子串的数组。 如果分隔符出现在字符串的开头或结尾,或者如果有多个连续的分隔符,则将在对应位置填充空的子串。

- splitByString(separator, s)
与上面相同,但它使用多个字符的字符串作为分隔符。 该字符串必须为非空。

## json函数
文档:https://clickhouse.tech/docs/en/sql-reference/functions/json-functions/
- visitParamHas(params, name)

- visitParamExtractRaw(params, name)
返回字段的值,包括分隔符。

解析双引号中的字符串,这个值没有进行转义。如果转义失败,则返回一个空字符串。
- visitParamExtractString(params, name)
解析 JSON 并提取字符串。这个函数类似于`visitParamExtractString`函数。

- JSONHas(json[, indices_or_keys]…)
如果JSON中存在该值,则返回`1`。
如果该值不存在,则返回`0`。

- JSONExtract(json[, indices_or_keys…], Return_type)
解析 JSON 并提取给定 ClickHouse 数据类型的值。
```
SELECT JSONExtract ('{"a": "hello", "b": [-100, 200.0, 300],"c":1}', 'c', 'Int64') AS value
```

~~~
-- 创建表
create table tb_json(cont String) engine=Memory;
-- 插入数据
insert into tb_json values
('{"movie":"1207","rate":"4","timeStamp":"978300719","uid":"1"}'),('{"movie":"2028","rate":"5","timeStamp":"978301619","uid":"1"}')
,('{"movie":"531","rate":"4","timeStamp":"978302149","uid":"1"}'),('{"movie":"3114","rate":"4","timeStamp":"978302174","uid":"1"}'),('{"movie":"608","rate":"4","timeStamp":"978301398","uid":"1"}');
SELECT cast(JSONExtract(cont, 'Tuple(String, String)').2,'Float64') from tb_json
~~~

- JSONExtractKeysAndValues(json[,indices_or_keys…],Value_type)
从 JSON 解析键值对,其中值是给定的 ClickHouse 数据类型。
~~~
SELECT JSONExtractKeysAndValues('{"x": {"a": 5, "b": 7, "c": 11}}', 'x', 'Int8') = [('a',5),('b',7),('c',11)];
~~~

## 漏斗模型链路函数
案例:
漏斗模型:分析用户行为

此类场景clickhouse提供了一个名叫windowFunnel的函数来实现
~~~SQL
-- 创建一张用户行为表,至少包含时间、事件、用户id
CREATE TABLE test.action
(
`uid` Int32,
`event_type` String,
`time` datetime
)
ENGINE = MergeTree()
PARTITION BY uid
ORDER BY xxHash32(uid)
SAMPLE BY xxHash32(uid)
SETTINGS index_granularity = 8192
-- 插入数据
insert into action values(1,'浏览','2020-01-02 11:00:00');
insert into action values(1,'点击','2020-01-02 11:10:00');
insert into action values(1,'下单','2020-01-02 11:20:00');
insert into action values(1,'支付','2020-01-02 11:30:00');
insert into action values(2,'下单','2020-01-02 11:00:00');
insert into action values(2,'支付','2020-01-02 11:10:00');
insert into action values(1,'浏览','2020-01-02 11:00:00');
insert into action values(3,'浏览','2020-01-02 11:20:00');
insert into action values(3,'点击','2020-01-02 12:00:00');
insert into action values(4,'浏览','2020-01-02 11:50:00');
insert into action values(4,'点击','2020-01-02 12:00:00');
insert into action values(5,'浏览','2020-01-02 11:50:00');
insert into action values(5,'点击','2020-01-02 12:00:00');
insert into action values(5,'下单','2020-01-02 11:10:00');
insert into action values(6,'浏览','2020-01-02 11:50:00');
insert into action values(6,'点击','2020-01-02 12:00:00');
insert into action values(6,'下单','2020-01-02 12:10:00');
~~~
以30分钟作为一个时间窗口,返回满足在指定滑动窗口内的连续触发条件的最大值。
~~~SQL
SELECT
user_id,
windowFunnel(1800)(time, event_type = '浏览', event_type = '点击', event_type = '下单', event_type = '支付') AS level
FROM
(
SELECT
time,
event_type,
uid AS user_id
FROM action
)
GROUP BY user_id
~~~
- ClickHouse
- 第一节 ClickHouse入门
- 1.1ClickHouse概述
- 1.2ClickHouse单机安装
- 1.3ClickHouse配置
- 1.4ClickHouse数据库引擎
- 1.5ClickHouse集群部署
- 第二节 ClickHouse进阶
- 2.1ClicKHouse数据类型
- 2.2ClicKHouse基本语法
- 2.3ClickHouse引擎
- 2.4ClickHouse函数
- 2.5ClickHouse分布式表
- 2.6ClickHouse权限和密码加密
- 2.7ClickHouse数据导入和导出
- 第三节 ClicKHouse实战篇
- 3.1ClickHouse的JDBC连接
- 3.2ClickHouse用户行为分析
- 3.3ClickHouse实战
- 第四节 ClicKHouse常见问题
- 4.1ClickHouse常见问题汇总
- 第五节 ClickHouse其他
- 5.1ClickHouse可视化工具
- 5.2ClickHouse学习教程