clickhouse之SQL語法--Functions

clickhouse之SQL語法–Functions

介紹

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.

比較函數

比較函數總是返回0或1 (Uint8)。

可以比較以下幾種類型:

  • numbers
  • strings and fixed strings
  • dates
  • dates with times

在每個組內,而不是在不同組之間。

例如,您不能將日期與字符串進行比較。必須使用函數將字符串轉換爲日期,反之亦然。

字符串按字節進行比較。一個較短的字符串比所有以它開頭並且包含至少一個字符的字符串都要小。

請注意。在1.1.54134版本之前,用與c++相同的方法比較帶符號和無符號的數字。換句話說,在選擇9223372036854775807 > -1這樣的情況下,可能會得到錯誤的結果。這種行爲在1.1.54134版本中發生了變化,現在在數學上是正確的。

equals, a = b and a == b operator
notEquals, a ! operator= b and a <> b
less, < operator
greater, > operator
lessOrEquals, <= operator
greaterOrEquals, >= operator

邏輯函數

邏輯函數接受任何數字類型,但返回一個等於0或1的UInt8數字。

作爲參數的Zero被認爲是“false”,而任何非零值都被認爲是“true”。

and, AND operator
or, OR operator
not, NOT operator
xor

類型轉換函數

toUInt8, toUInt16, toUInt32, toUInt64
toInt8, toInt16, toInt32, toInt64
toFloat32, toFloat64
toDate, toDateTime
toUInt8OrZero, toUInt16OrZero, toUInt32OrZero, toUInt64OrZero, toInt8OrZero, toInt16OrZero, toInt32OrZero, toInt64OrZero, toFloat32OrZero, toFloat64OrZero, toDateOrZero, toDateTimeOrZero
toUInt8OrNull, toUInt16OrNull, toUInt32OrNull, toUInt64OrNull, toInt8OrNull, toInt16OrNull, toInt32OrNull, toInt64OrNull, toFloat32OrNull, toFloat64OrNull, toDateOrNull, toDateTimeOrNull
toDecimal32(value, S), toDecimal64(value, S), toDecimal128(value, S)

toString

用於在數字、字符串(但不是固定字符串)、日期和日期與時間之間進行轉換的函數。所有這些函數都接受一個參數。

在轉換爲字符串或從字符串轉換時,將使用與選項卡分隔格式(以及幾乎所有其他文本格式)相同的規則對值進行格式化或解析。如果無法解析字符串,則拋出異常並取消請求。

當將日期轉換爲數字或反之亦然時,日期對應自Unix紀元開始以來的天數。當將日期與時間轉換爲數字或反之亦然時,日期與時間對應自Unix紀元開始以來的秒數。

toDate/toDateTime函數的date和date-with-time格式定義如下:

YYYY-MM-DD
YYYY-MM-DD hh:mm:ss

作爲一個例外,如果從UInt32、Int32、UInt64或Int64數字類型轉換到日期,並且該數字大於或等於65536,則該數字將被解釋爲Unix時間戳(而不是天數),並四捨五入到日期。這允許支持寫入“toDate(unix_timestamp)”的常見情況,否則這將是一個錯誤,需要編寫更麻煩的“toDate(toDateTime(unix_timestamp))”。

日期和帶時間的日期之間的轉換以一種自然的方式執行:添加一個空時間或刪除時間。

在c++中,數值類型之間的轉換使用與不同數值類型之間的賦值相同的規則。

此外,DateTime參數的toString函數可以接受包含時區名稱的第二個字符串參數。例如:Asia/Yekaterinburg在本例中,時間是按照指定的時區格式化的。

SELECT
    now() AS now_local,
    toString(now(), 'Asia/Yekaterinburg') AS now_yekat
┌───────────now_local─┬─now_yekat───────────┐
│ 2016-06-15 00:11:21 │ 2016-06-15 02:11:21 │
└─────────────────────┴─────────────────────┘

還請參見toUnixTimestamp函數.

toFixedString (s,N)

將字符串類型參數轉換爲FixedString(N)類型(長度爲N的字符串)。N必須是常量。如果字符串的字節數小於N,則向右傳遞null字節。如果字符串的字節數超過N,則拋出異常。

toStringCutToZero (s)

接受字符串或FixedString參數。返回在找到的第一個零字節處截斷內容的字符串。

例子:

SELECT toFixedString('foo', 8) AS s, toStringCutToZero(s) AS s_cut
┌─s─────────────┬─s_cut─┐
│ foo\0\0\0\0\0 │ foo   │
└───────────────┴───────┘
SELECT toFixedString('foo\0bar', 8) AS s, toStringCutToZero(s) AS s_cut
┌─s──────────┬─s_cut─┐
│ foo\0bar\0 │ foo   │
└────────────┴───────┘

reinterpretAsUInt8, reinterpretAsUInt16, reinterpretAsUInt32, reinterpretAsUInt64
reinterpretAsInt8, reinterpretAsInt16, reinterpretAsInt32, reinterpretAsInt64
reinterpretAsFloat32, reinterpretAsFloat64
reinterpretAsDate, reinterpretAsDateTime

這些函數接受字符串並將字符串開頭的字節解釋爲按主機順序排列的數字(小端)。如果字符串不夠長,函數的工作方式就像用必要的空字節數填充字符串一樣。如果字符串比需要的長,則忽略額外的字節。日期被解釋爲自Unix紀元開始以來的天數,帶有時間的日期被解釋爲自Unix紀元開始以來的秒數。

reinterpretAsString

該函數接受一個數字、日期或帶時間的日期,並返回一個字符串,其中包含以主機順序(小端)表示相應值的字節。空字節從末尾刪除。例如,UInt32類型值255是一個長度爲一個字節的字符串。

reinterpretAsFixedString

該函數接受一個數字、日期或帶時間的日期,並返回一個FixedString,其中包含以主機順序(小端)表示相應值的字節。空字節從末尾刪除。例如,UInt32類型值255是一個固定字符串,長度爲一個字節。

CAST(x, t)

將“x”轉換爲“t”數據類型。還支持語法轉換(x作爲t)。

例子:

SELECT
    '2016-06-15 23:00:00' AS timestamp,
    CAST(timestamp AS DateTime) AS datetime,
    CAST(timestamp AS Date) AS date,
    CAST(timestamp, 'String') AS string,
    CAST(timestamp, 'FixedString(22)') AS fixed_string
┌─timestamp───────────┬────────────datetime─┬───────date─┬─string──────────────┬─fixed_string──────────────┐
│ 2016-06-15 23:00:00 │ 2016-06-15 23:00:00 │ 2016-06-15 │ 2016-06-15 23:00:00 │ 2016-06-15 23:00:00\0\0\0 │
└─────────────────────┴─────────────────────┴────────────┴─────────────────────┴───────────────────────────┘

轉換爲FixedString(N)只適用於String或FixedString(N)類型的參數。

支持將類型轉換爲Nullable和back。例子:

SELECT toTypeName(x) FROM t_null

┌─toTypeName(x)─┐
│ Int8          │
│ Int8          │
└───────────────┘

SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null

┌─toTypeName(CAST(x, 'Nullable(UInt16)'))─┐
│ Nullable(UInt16)                        │
│ Nullable(UInt16)                        │
└─────────────────────────────────────────┘

toIntervalYear, toIntervalQuarter, toIntervalMonth, toIntervalWeek, toIntervalDay, toIntervalHour, toIntervalMinute, toIntervalSecond

將數字類型參數轉換爲區間類型(持續時間)。interval類型實際上非常有用,您可以使用這種類型的數據直接對Date或DateTime執行算術操作。同時,ClickHouse爲聲明間隔類型數據提供了更方便的語法。例如:

WITH
    toDate('2019-01-01') AS date,
    INTERVAL 1 WEEK AS interval_week,
    toIntervalWeek(1) AS interval_to_week
SELECT
    date + interval_week,
    date + interval_to_week
┌─plus(date, interval_week)─┬─plus(date, interval_to_week)─┐
│                2019-01-08 │                   2019-01-08 │
└───────────────────────────┴─────────────────────

parseDateTimeBestEffort

將數字類型參數解析爲日期或DateTime類型。與toDate和toDateTime不同,parseDateTimeBestEffort可以改進更復雜的日期格式。有關更多信息,請參見鏈接:複雜日期格式

parseDateTimeBestEffortOrNull

與parseDateTimeBestEffort相同,只是當遇到無法處理的日期格式時返回null。

parseDateTimeBestEffortOrZero

與parseDateTimeBestEffort相同,只是當遇到無法處理的日期格式時,它返回零日期或零日期時間。

爲數組服務的函數

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”.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章