## 高階函數
高階函數、`->`運算符和 lambda(params, expr) 函數
[https://clickhouse.tech/docs/en/sql-reference/functions/](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/](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/](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/](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/](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.1 ClickHouse概述
- 1.2 ClickHouse單機安裝
- 1.3 ClickHouse配置
- 1.4 ClickHouse數據庫引擎
- 1.5 ClickHouse集群部署
- 第二節 ClickHouse進階
- 2.1 ClicKHouse數據類型
- 2.2 ClicKHouse基本語法
- 2.3 ClickHouse引擎
- 2.4 ClickHouse函數
- 2.5 ClickHouse分布式表
- 2.6 ClickHouse權限和密碼加密
- 2.7 ClickHouse數據導入和導出
- 第三節 ClicKHouse實戰篇
- 3.1 ClickHouse的JDBC連接
- 3.2 ClickHouse用戶行為分析
- 3.3 ClickHouse實戰
- 第四節 ClicKHouse常見問題
- 4.1 ClickHouse常見問題匯總
- 第五節 ClickHouse其他
- 5.1 ClickHouse可視化工具
- 5.2 ClickHouse學習教程