Clickhouse 函數基礎入門

Clickhouse 基礎知識 - 函數


--------------------------------------------------
---------------Clickhouse基礎知識:函數學習-------------
--官址學習文檔:https://clickhouse.yandex/docs/zh/
--------------------------------------------------

-- DBeaver6.1.2操作快捷鍵:
-- 常用快捷鍵須知:(Ctrl + Shift + L 顯示快捷鍵列表)
-- 1.刪除光標所在行:Ctrl + D
-- 2.複製光標所在行:Ctrl + Alt + ↓
-- 3.移動光標所在行:Ctrl + Shift + ↑/↓
-- 4.縮小SQL編輯器的文本字體大小:Ctrl + -/+
-- 5.查找:Ctrl + F
-- 6.選中上或下的SQL執行語句:Alt + ↑/↓
-- 7.執行當前光標所在SQL語句(無論是否格式化過,前提是此SQL語句和上一條有空行或者上一條SQL語句有分號“;”隔開)
----------------------------------------------------------------------------

-- 零、檢測函數類型(clickhouse中數據的類型)
SELECT toTypeName(0);-- UInt8(三位數爲8)
SELECT toTypeName(-0);-- Int8
SELECT toTypeName(-343);-- Int16
SELECT toTypeName(12.43); -- Float64(默認浮點型的數據爲64),所以一般在處理浮點型的數據的時候儘量轉成toFloat32(12.43)
SELECT toTypeName(12.34343); -- Float64
SELECT toTypeName(toDateTime(1502396027)); -- DateTime

-- 一、算數函數
-->>>>>> 算數函數(數學上的計算)
--求和
SELECT plus(12, 21), plus(10, -10), plus(-10, -10);
--差值
SELECT minus(10, 5), minus(10, -10),minus(-10, -10);
--積
SELECT multiply(12, 2), multiply(12, -2), multiply(-12, -2);
--平均值
SELECT divide(12, 4), divide(10, 3), divide(2, 4), divide(-4, -2), divide(-4, 2), divide(-4.5, 3);
SELECT intDiv(10, 3), divide(10, 3); -- 3, 3.333(保留四位有效數字)
SELECT divide(10, 0), divide(-10, 0); -- 出現無窮大字符“ ∞ ”或“ -∞ ”
SELECT divide(0, 0); -- 特殊字符(類似亂碼)
SELECT intDivOrZero(10, 0); -- 0
--求餘數
SELECT modulo(10, 3); --1
SELECT modulo(10.5, 3); --1
--取反
SELECT negate(10), negate(-10); -- -10 10
--絕對值
SELECT abs(-10), abs(10);
--最大公約數
SELECT gcd(12, 24), gcd(-12, -24), gcd(-12, 24);
--最小公倍數
SELECT lcm(12, 24), lcm(-12, -24), lcm(-3, 4);

-- 二、比較函數
-->>>>>> 比較函數(始終返回0表示false 或 1表示true)
SELECT 12 == 12, 12 != 10, 12 == 132, 12 != 12, 12 <> 12;
SELECT equals(12, 12), notEquals(12, 10), equals(12, 10), notEquals(12,123);
SELECT greater(12, 10), greater(10, 12), greater(12, 12);-- 前者是否大於後者
SELECT greaterOrEquals(12,10), greaterOrEquals(12,12);-- 前者是否大於或等於後者
SELECT less(12, 21), less(12, 10), less(120, 120);-- 前者是否小於後者
SELECT lessOrEquals(12, 120), lessOrEquals(12, 12);-- 前世是否小於或等於或者

-- 三、邏輯函數
-->>>>>> 邏輯操作符(返回0表示false 或 1表示true)
SELECT 12==12 or 12!=10;
SELECT 12==12 and 12!=10;
SELECT not 12, not 0;
SELECT or(equals(12, 12), notEquals(12, 10)); --函數表示法:或
SELECT and(equals(12, 12), notEquals(12, 10));--函數表示法:且
SELECT not(12), not(0);

-- 四、類型轉換函數
-->>>>>> 類型轉換函數部分示例:
SELECT toInt8(12.3334343), toFloat32(10.001), toFloat64(1.000040);
SELECT toString(now());
SELECT now() AS now_local, toString(now(), 'Asia/Yekaterinburg') AS now_yekat;
SELECT now() AS now_local, toDate(now()), toDateTime(now()), toUnixTimestamp(now());

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;

WITH
toDate('2019-01-01') AS date,
INTERVAL 1 WEEK AS interval_week,
toIntervalWeek(1) AS interval_to_week,
toIntervalMonth(1) AS interval_to_month
SELECT
date + interval_week,
date + interval_to_week,
date + interval_to_month;

WITH
toDateTime('2019-01-01 12:10:10') as datetime,
INTERVAL 1 HOUR AS interval_hour,
toIntervalHour(1) as invterval_to_hour
SELECT
plus(datetime, interval_hour),
plus(datetime, invterval_to_hour);

-- 五、時間日期函數
--->>>>>> 時間日期函數
SELECT
toDateTime('2019-07-30 10:10:10') AS time,
-- 將DateTime轉換成Unix時間戳
toUnixTimestamp(time) as unixTimestamp,
-- 保留 時-分-秒
toDate(time) as date_local,
toTime(time) as date_time,-- 將DateTime中的日期轉換爲一個固定的日期,同時保留時間部分。
-- 獲取年份,月份,季度,小時,分鐘,秒鐘
toYear(time) as get_year,
toMonth(time) as get_month,
-- 一年分爲四個季度。1(一季度:1-3),2(二季度:4-6),3(三季度:7-9),4(四季度:10-12)
toQuarter(time) as get_quarter,
toHour(time) as get_hour,
toMinute(time) as get_minute,
toSecond(time) as get_second,
-- 獲取 DateTime中的當前日期是當前年份的第幾天,當前月份的第幾日,當前星期的周幾
toDayOfYear(time) as "當前年份中的第幾天",
toDayOfMonth(time) as "當前月份的第幾天",
toDayOfWeek(time) as "星期",
toDate(time, 'Asia/Shanghai') AS date_shanghai,
toDateTime(time, 'Asia/Shanghai') AS time_shanghai,
-- 得到當前年份的第一天,當前月份的第一天,當前季度的第一天,當前日期的開始時刻
toStartOfYear(time),
toStartOfMonth(time),
toStartOfQuarter(time),
toStartOfDay(time) AS cur_start_daytime,
toStartOfHour(time) as cur_start_hour,
toStartOfMinute(time) AS cur_start_minute,
-- 從過去的某個固定的時間開始,以此得到當前指定的日期的編號
toRelativeYearNum(time),
toRelativeQuarterNum(time);

SELECT
toDateTime('2019-07-30 14:27:30') as time,
toISOYear(time) AS iso_year,
toISOWeek(time) AS iso_week,
now() AS cur_dateTime1, -- 返回當前時間yyyy-MM-dd HH:mm:ss
today() AS cur_dateTime2, -- 其功能與'toDate(now())'相同
yesterday() AS yesterday, -- 當前日期的上一天
-- timeSlot(1) AS timeSlot_1, -- 出現異常!!將時間向前取整半小時
toDate(time) as getY_M_d;

-- 目前只有這三種格式,沒有什麼toYYYY(),toYYYddmm()之類的函數,不要想當然。
SELECT
now() as nowTime,
-- 將Date或DateTime轉換爲包含年份和月份編號的UInt32類型的數字(YYYY * 100 + MM)
toYYYYMMDDhhmmss(nowTime),
toYYYYMMDD(nowTime),
toYYYYMM(nowTime);

-- formatDateTime(Time, Format[,Timezone])函數引用
SELECT
now() as now_time,
toDateTime('2019-07-31 18:20:30') AS def_datetime,
formatDateTime(now_time, '%D') AS now_time_day_month_year,-- 07/30/19
-- toDateTime('2019-07-31 18:20:30', 'Asia/Shanghai') AS def_datetime1, -- 指定時區
formatDateTime(def_datetime, '%Y') AS def_datetime_year, -- 2019(指定日期爲2019年)
formatDateTime(def_datetime, '%y') AS def_datetime_year_litter, -- 19(指定日期爲19年,Year, last two digits (00-99),本世紀的第19年)
formatDateTime(def_datetime, '%H') AS hour24, -- 18 下午六點
formatDateTime(def_datetime, '%I') AS hour12, -- 06下午六點
formatDateTime(def_datetime, '%p') AS PMorAM, -- 指定時間是上午還是下午
formatDateTime(def_datetime, '%w') AS def_datetime_get_curWeek,-- 3(指定日期爲星期三)
formatDateTime(def_datetime, '%F') AS def_datetime_get_date,-- 2019-07-31
formatDateTime(def_datetime, '%T') AS def_datetime_get_time,-- 18:20:30
formatDateTime(def_datetime, '%M') AS def_datetime_get_minute,-- 20(得到指定事件的“分”,minute (00-59))
formatDateTime(def_datetime, '%S') AS def_datetime_get_second;-- 30(得到指定事件的“秒”,second (00-59))

 

-- 1.跳轉到之後的日期函數
-- 第一種,日期格式(指定日期,需注意時區的問題)
WITH
toDate('2019-09-09') AS date,
toDateTime('2019-09-09 00:00:00') AS date_time
SELECT
addYears(date, 1) AS add_years_with_date,
addYears(date_time, 0) AS add_years_with_date_time;
-- 第二種,日期格式(當前,本地時間)
WITH
toDate(now()) as date,
toDateTime(now()) as date_time
SELECT
now() as now_time,-- 當前時間
addYears(date, 1) AS add_years_with_date,-- 之後1年
addYears(date_time, 1) AS add_years_with_date_time,
addMonths(date, 1) AS add_months_with_date,-- 之後1月
addMonths(date_time, 1) AS add_months_with_date_time,
addWeeks(date, 1) AS add_weeks_with_date,--之後1周
addWeeks(date_time, 1) AS add_weeks_with_date_time,
addDays(date, 1) AS add_days_with_date,-- 之後1天
addDays(date_time, 1) AS add_days_with_date_time,
addHours(date_time, 1) AS add_hours_with_date_time,--之後1小時
addMinutes(date_time, 1) AS add_minutes_with_date_time,--之後1分中
addSeconds(date_time, 10) AS add_seconds_with_date_time,-- 之後10秒鐘
addQuarters(date, 1) AS add_quarters_with_date, -- 之後1個季度
addQuarters(date_time, 1) AS add_quarters_with_date_time;

-- 2.跳轉到當前日期之前的函數(函數將Date/DateTime減去一段時間間隔,然後返回Date/DateTime)
WITH
toDate(now()) as date,
toDateTime(now()) as date_time
SELECT
subtractYears(date, 1) AS subtract_years_with_date,
subtractYears(date_time, 1) AS subtract_years_with_date_time,
subtractQuarters(date, 1) AS subtract_Quarters_with_date,
subtractQuarters(date_time, 1) AS subtract_Quarters_with_date_time,
subtractMonths(date, 1) AS subtract_Months_with_date,
subtractMonths(date_time, 1) AS subtract_Months_with_date_time,
subtractWeeks(date, 1) AS subtract_Weeks_with_date,
subtractWeeks(date_time, 1) AS subtract_Weeks_with_date_time,
subtractDays(date, 1) AS subtract_Days_with_date,
subtractDays(date_time, 1) AS subtract_Days_with_date_time,
subtractHours(date_time, 1) AS subtract_Hours_with_date_time,
subtractMinutes(date_time, 1) AS subtract_Minutes_with_date_time,
subtractSeconds(date_time, 1) AS subtract_Seconds_with_date_time;

SELECT toDate('2019-07-31', 'Asia/GuangZhou') as date_guangzhou;
SELECT toDate('2019-07-31'), toDate('2019-07-31', 'Asia/Beijing') as date_beijing;
-- 亞洲只能加載上海的timezone???
SELECT toDateTime('2019-07-31 10:10:10', 'Asia/Shanghai') as date_shanghai;


-- 計算連個時刻在不同時間單位下的差值
-- 第一種:指定時間計算差值示例
WITH
toDateTime('2019-07-30 10:10:10', 'Asia/Shanghai') as date_shanghai_one,
toDateTime('2020-10-31 11:20:30', 'Asia/Shanghai') as date_shanghai_two
SELECT
dateDiff('year', date_shanghai_one, date_shanghai_two) as diff_years,
dateDiff('month', date_shanghai_one, date_shanghai_two) as diff_months,
dateDiff('week', date_shanghai_one, date_shanghai_two) as diff_week,
dateDiff('day', date_shanghai_one, date_shanghai_two) as diff_days,
dateDiff('hour', date_shanghai_one, date_shanghai_two) as diff_hours,
dateDiff('minute', date_shanghai_one, date_shanghai_two) as diff_minutes,
dateDiff('second', date_shanghai_one, date_shanghai_two) as diff_seconds;

-- 第二種:本地當前時間示例
WITH
now() as date_time
SELECT
dateDiff('year', date_time, addYears(date_time, 1)) as diff_years,
dateDiff('month', date_time, addMonths(date_time, 2)) as diff_months,
dateDiff('week', date_time, addWeeks(date_time, 3)) as diff_week,
dateDiff('day', date_time, addDays(date_time, 3)) as diff_days,
dateDiff('hour', date_time, addHours(date_time, 3)) as diff_hours,
dateDiff('minute', date_time, addMinutes(date_time, 30)) as diff_minutes,
dateDiff('second', date_time, addSeconds(date_time, 35)) as diff_seconds;

-- timeSlot(StartTime, Duration, [,Size])
-- 它返回一個時間數組,其中包括從從“StartTime”開始到“StartTime + Duration 秒”內的所有符合“size”(以秒爲單位)步長的時間點
-- 作用:搜索在相應會話中綜合瀏覽量是非常有用的。
SELECT
timeSlots(toDateTime('2012-01-01 12:20:00'), toUInt32(600)) as dateTimeArray,
dateTimeArray[0] as arr_index_0, -- no result.
dateTimeArray[1] as arr_index_1, -- 2012-01-01 20:00:00
dateTimeArray[2] as arr_index_2, -- 2012-01-01 20:30:00
dateTimeArray[3] as arr_index_3, -- no result.
dateTimeArray[4] as arr_index_4; -- no result.
-- toUInt32(600) 表示之後間距20秒的時刻
SELECT
timeSlots(now(), toUInt32(600), 20) as dateTimeArray, -- 類似於:引用地址
dateTimeArray[0] as arr_index_0, -- no result.爲什麼?
dateTimeArray[1] as arr_index_1,
dateTimeArray[2] as arr_index_2,
dateTimeArray[3] as arr_index_3,
dateTimeArray[4] as arr_index_4,
dateTimeArray[5] as arr_index_5;
-- 指定時間爲基準,之後每個元素增加20秒
SELECT
timeSlots(toDateTime('2012-01-01 12:20:00'), toUInt32(600), 20) as cur_dateTimeArray, -- 類似於:引用地址
cur_dateTimeArray[0] as arr_index_0, -- no result.爲什麼?
cur_dateTimeArray[1] as arr_index_1, -- 2012-01-01 20:20:00
cur_dateTimeArray[2] as arr_index_2, -- 2012-01-01 20:20:20
cur_dateTimeArray[3] as arr_index_3, -- 2012-01-01 20:20:40
cur_dateTimeArray[4] as arr_index_4, -- 2012-01-01 20:21:00
cur_dateTimeArray[5] as arr_index_5; -- 2012-01-01 20:21:20


-- 六、字符串函數
--->>>>>> 字符串函數:
SELECT
length('hello world') as str_length, -- 按照Unicode編碼計算長度“你好”的長度爲6
empty('hello world'),-- 判斷字符串是否爲空,空爲1,非空爲0
notEmpty('hello world'),
lengthUTF8('hello world'), -- 按照實際字符計算長度“你好”爲2
char_length('hello world'), -- 同 lengthUTF8()
character_length('hello world'), -- 同 lengthUTF8(),
lower('abcd123--'),--字母全部小寫(將字符串中的ASCII轉換爲小寫。)
upper('abcd123--'),--字母全部大寫(將字符串中的ASCII轉換爲大寫。)
lowerUTF8('abcd123-/*\8asd-\\'), -- abcd123-/*8asd-\
upperUTF8('abcd123--'), -- ABCD123--
isValidUTF8('abcd123--/*\*'); --檢查字符串是否爲有效的UTF-8編碼,是則返回1,否則返回0。
SELECT notEmpty(''), notEmpty(NULL), notEmpty('he'); -- 0,空,1
SELECT toValidUTF8('\x61\xF0\x80\x80\x80b');
-- reverseUTF8():以Unicode字符爲單位反轉UTF-8編碼的字符串。如果字符串不是UTF-8編碼,則可能獲取到一個非預期的結果(不會拋出異常)
SELECT reverse('abcdefg'), reverseUTF8('abcdefg');
-- 2.字符串維度自定義安排
SELECT format('{1} {0} {1}', 'World', 'Hello'); -- 輸出:Hello World Hello
SELECT format('{0} {0} {1} {1}', 'one', 'two'); -- 輸出:one one two two
SELECT format('{} {}', 'Hello', 'World'); -- 輸出:Hello World
-- 3.字符串拼接 concat(s1,s2,s3,...)
SELECT concat('Hello',' ','World', '!');-- Hello World!
-- 與concat相同,區別在於,你需要保證concat(s1, s2, s3) -> s4是單射的,它將用於GROUP BY的優化。
SELECT concatAssumeInjective('Hello',' ','World', '!');-- Hello World!
-- 4.字符串截取:substring(s, offset, length), mid(s, offset, length), substr(s, offset, length)
-- 以字節爲單位截取指定位置字符串,返回以‘offset’位置爲開頭,長度爲‘length’的子串。‘offset’從1開始(與標準SQL相同)。‘offset’和‘length’參數必須是常量。
SELECT
substring('abcdefg', 1, 3),-- abc
substring('你好,世界', 1, 3),-- 你
substringUTF8('你好,世界', 1, 3); -- 你好,
-- 5.字符串拼接:appendTrailingCharIfAbsent(s, c)
-- 如果‘s’字符串非空並且末尾不包含‘c’字符,則將‘c’字符附加到末尾。
SELECT
appendTrailingCharIfAbsent('good','c'), -- goodc
appendTrailingCharIfAbsent('goodccc','c'); -- goodccc
-- 6.字符串編碼轉換:convertCharset(s, from, to) 返回從‘from’中的編碼轉換爲‘to’中的編碼的字符串‘s’。
SELECT
convertCharset('hello', 'UTF8','Unicode'),-- ��h
convertCharset('hello', 'Unicode', 'UTF8'),-- 橋汬�
convertCharset('hello', 'Unicode', 'ASCII'),--
convertCharset('hello', 'ascii', 'ascii'),--hello
convertCharset('hello', 'UTF8','UTF8');-- hello
SELECT
base64Encode('username+password'),-- dXNlcm5hbWUrcGFzc3dvcmQ=
base64Decode('dXNlcm5hbWUrcGFzc3dvcmQ='), -- username+password
-- 使用base64將字符串解碼成原始字符串。但如果出現錯誤,將返回空字符串。
tryBase64Decode('dXNlcm5hbWUrcGFzc3dvcmQ=');
-- 7.判斷字符串是否已什麼結尾或結束,返回1:true,0:flase
-- endsWith(s, suffix) 返回是否以指定的後綴結尾。如果字符串以指定的後綴結束,則返回1,否則返回0
-- startWith(s, prefix) 返回是否以指定的前綴開頭。如果字符串以指定的前綴開頭,則返回1,否則返回0。
SELECT
endsWith('string','g'),
startsWith('string', 'str'); -- 1 true
-- 8.刪除左側空白字符
-- trimLeft(s) 返回一個字符串,用於刪除左側的空白字符
-- trimRight(s) 返回一個字符串,用於刪除右側的空白字符
-- trimBoth(s) 返回一個字符串,用於刪除左側和右側的空白字符
SELECT
trimLeft(' sdfdgs'), -- sdfdgs
trimRight('abcd '), -- abcd
trimBoth(' abcd '); -- abcd

-- 七、字符串搜索函數
--->>>>>> 字符串搜索函數
-- pasition(haystack, needle), 顯示needle在haystack的第一個出現的位置。
SELECT
POSITION('2121stringstrstrstrstr','str') AS positionSearch, -- 5
POSITION('你好,hello,12323-你好,你,好sdfd*dg', '你,好'),-- 31
positionUTF8('n12你好','你好') AS positionUTF8,-- 4
positionCaseInsensitive('ABCDCDEFABCD','bc') AS positionCaseInsensitive, --2
locate('hellohellohellohello','ello'); -- 2
-- multiSearchAllPositions(haystack, [needle1, needle2, ..., needlen])
-- 注意:在所有multiSearch*函數中,由於實現規範,needles的數量應小於2^8。
-- 函數返回一個數組,其中包含所有匹配needlei的位置
SELECT
multiSearchAllPositions('goodnamegoodnamegoodhellohihihi', ['dn', 'good']) as multiSearch,-- [4,1]
multiSearchAllPositionsCaseInsensitive('nameSsdfagpSSDFDFetgfderef', ['SS','fa']) as multiCaseInsensitive,
multiSearchAllPositionsUTF8('nameSsdfazz軸功率gpSSDFDFetgfderef', ['Ss','fa', 'zz軸']) AS multiSearchUTF8,
multiSearchAllPositionsCaseInsensitiveUTF8('nameSsdfazz軸功率gpSSDFDFetgfderef', ['Ss','fa', 'zz軸']) AS multiCaseInsensitiveUTF8;
-- 檢查字符串是否與pattern正則表達式匹配。pattern可以是一個任意的re2正則表達式。 re2正則表達式的語法比Perl正則表達式的語法存在更多限制。
-- match(haystack, pattern) 匹配到了則返回1,否則返回0
SELECT
match('1232434sadgaDDFSrefds', '[0-9a-zA-Z]'), -- 存在匹配的字符,返回1
match('1232321', '[a-z]'); -- 不存在匹配的字符,返回0
-- 與match相同,但如果所有正則表達式都不匹配,則返回0;如果任何模式匹配,則返回1。它使用hyperscan庫。對於在字符串中搜索子字符串的模式,最好使用“multisearchany”,因爲它更高效。
-- multiMatchAny(haystack, [pattern1, pattern2, ..., patternn])
-- 注意:任何haystack字符串的長度必須小於232字節,否則拋出異常。這種限制是因爲hyperscan API而產生的。
-- 多個正則表達式對原始字符進行匹配,如若只有一個正則表達式匹配上了則返回1,否則返回0
SELECT
multiMatchAny('abcABC',['[0-9]','[a-zA-Z]']) AS multiMatchAnyOne, -- 1
multiMatchAny('123abcABC',['[0-9]','[a-zA-Z]']) AS multiMatchAnyTwo, --1
-- 與multiMatchAny相同,但返回與haystack匹配的任何內容的索引位置。
multiMatchAnyIndex('123abcABC', ['[0-9]','[a-zA-Z]']) as multiMatchAnyIndex; --2
-- 模糊匹配:like()函數,注意大寫敏感。
-- % 表示任何字節數(包括零字符)
-- _ 表示任何一個字節
SELECT
'hello' LIKE '%h%' as LIKE_UP, -- 1
'hello' like 'he' AS like_low, -- 0
'hello' not like 'he' AS not_like, -- 1
'hello' like '%he%' AS like_litter, -- 1
like('adgadgadfa1232', '_12_') AS like_func,
like('sdfasdfasd', '[a-z]') AS like_func2, -- 0
notLike('1232423', '[a-zA-Z]') AS not_like_func; -- 1
-- 使用字符串截取字符串:extract(haystack, pattern)
-- 使用正則表達式截取字符串。如果‘haystack’與‘pattern’不匹配,則返回空字符串。如果正則表達式中不包含子模式,它將獲取與整個正則表達式匹配的子串。否則,它將獲取與第一個子模式匹配的子串。
SELECT
extractAll('hellogoodaimantIdeaIDEAfasd123232', '[0-9]'), -- ['1','2','3','2','3','2']
extractAll('12323dSDFRE', '[A-Z]'),-- ['S','D','F','R','E']
extract('helloclickhouse', '[a-z]');-- h
-- ngramSearch(haystack, needle)
-- 基於4-gram計算haystack和needle之間的距離:計算兩個4-gram集合之間的對稱差異,並用它們的基數和對其進行歸一化。
-- 返回0到1之間的任何浮點數 -- 越接近0則表示越多的字符串彼此相似。
-- 如果常量的needle或haystack超過32KB,函數將拋出異常。如果非常量的haystack或needle字符串超過32Kb,則距離始終爲1。
SELECT
ngramDistance('hello123456789','123') AS ngramDistance,
ngramDistanceCaseInsensitive('hello123456789','123') AS ngramDistanceCaseInsensitive,
ngramDistanceUTF8('hello123456789','123') AS ngramDistanceUTF8,
ngramDistanceCaseInsensitiveUTF8('hello123456789','123') AS ngramDistanceCaseInsensitiveUTF8;
-- 注意:對於UTF-8,我們使用3-gram。所有這些都不是完全公平的n-gram距離。
-- 我們使用2字節哈希來散列n-gram,然後計算這些哈希表之間的(非)對稱差異 - 可能會發生衝突。
-- 對於UTF-8不區分大小寫的格式,我們不使用公平的tolower函數
-- 我們將每個Unicode字符字節的第5位(從零開始)和字節的第一位歸零
-- 這適用於拉丁語,主要用於所有西裏爾字母。

--八、字符串替換函數
--->>>>>> 字符串替換函數
-- 替換匹配到的字符串
-- replaceOne(haystack, pattern, replacement)
-- 用‘replacement’子串替換‘haystack’中與‘pattern’子串第一個匹配的匹配項(如果存在)。 ‘pattern’和‘replacement’必須是常量。
-- replaceAll(haystack, pattern, replacement), replace(haystack, pattern, replacement)
-- 用‘replacement’子串替換‘haystack’中出現的所有‘pattern’子串。
SELECT
replaceOne('hed1234544', '4', '*') AS replaceOne,-- hed123*544
replaceRegexpOne('hed1234544', '4', '*') AS replaceRegexpOne,-- hed123*544
replace('hed1234544', '4', '*') AS replace, -- hed123*5**
replaceAll('hed1234544', '4', '*') AS replaceAll;-- hed123*5**

-- 實例:2019-07-31 改變成 07/31/2019
SELECT
toDate(now()) AS now_date,
replaceRegexpOne(toString(now_date), '(\\d{4})-(\\d{2})-(\\d{2})', '\\2/\\3/\\1') AS format_date;
-- 示例:賦值字符串10次
SELECT replaceRegexpOne('Hello, World!', '.*', '\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0') AS res;
-- replaceRegexpAll(haystack, pattern, replacement)
-- 與replaceRegexpOne相同,但會替換所有出現的匹配項。例如:
SELECT replaceRegexpAll('hello,world!', '.', '\\0\\0') as res; -- hheelllloo,,wwoorrlldd!!
SELECT replaceRegexpAll('hello o o, world.', ' ', '*') as res; -- hello*o*o,*world.

-- 函數:regexpQuoteMeta(s) 該函數用於在字符串中的某些預定義字符之前添加反斜槓。
-- 預定義字符:'0','\','|','(',')','^','$','。','[',']','?','* ','+','{',':',' - '。
-- 這個實現與re2 :: RE2 :: QuoteMeta略有不同。它以\0而不是\x00轉義零字節,它只轉義所需的字符
---- 簡言之,就是不處理轉義字符,一般如果沒有用的這個函數,都會有轉義的情況出現。
SELECT regexpQuoteMeta('\\\\|[]{}+_-=@!~`&^*%$#'); -- \\\\\|\[\]\{}\+_\-=@!~`&\^\*%\$#
SELECT toString('\\\\'); -- \\


--九、條件函數
--->>>>>> 條件函數
-- 1. if(cond, then, else)函數:類似於三元操作符。
-- 中文字符使用雙引號,英文字符可不使用引號也可使用當引號或雙引號,根據具體情況而定。
-- 如果cond != 0則返回then,如果cond = 0則返回else。 cond必須是UInt8類型,then和else必須存在最低的共同類型。
-- 注意:then和else可以是NULL
SELECT
12 > 10 ? 'desc' : 'asc' AS "三元操作符",
if(12 > 10, 'desc' , 'asc') AS "if()函數",
if(12 > 10, NULL, NULL);
-- 2. multiIf(cond_1, then_1, cond_2, then_2...else)
-- 允許您在查詢中更緊湊地編寫CASE運算符。類似於java中的switch語法(可以接受2n+1個參數)
SELECT multiIf(1,'one',2,'two',3,'three','not this index');-- 關聯case條件表達式

--十、數學函數
--->>>>>> 數學函數
SELECT
1 * e() AS E,
1 * pi() AS PI,
sqrt(25) AS sqrt_25, --接受一個數值類型的參數並返回它的平方根。
cbrt(27) AS cbrt_27, --接受一個數值類型的參數並返回它的立方根。
exp(10), --接受一個數值類型的參數並返回它的指數
exp10(10), --接受一個數值類型的參數並返回它的10的x次冪。
log(10) AS LOG,
log2(10) AS LOG2, --接受一個數值類型的參數並返回它的底2對數。
ln(e()) AS LOG10; --接受一個數值類型的參數並返回它的自然對數
-- 示例:三西格瑪準則
SELECT erf(3 / sqrt(2)); -- 0.997
SELECT
sin(90), -- 返回x的三角正弦值。
cos(90), -- 返回x的三角餘弦值。
tan(90), -- 返回x的三角正切值
acos(0), -- 返回x的反三角餘弦值。
asin(1), -- 返回x的反三角正弦值。
atan(45); -- 返回x的反三角正切值。
-- pow(x, y), power(x, y) 接受x和y兩個參數。返回x的y次方。
SELECT
pow(2, 3), -- 2的三次方
pow(3, 2); -- 3的平方
SELECT
intExp2(4), --2^4 接受一個數值類型的參數並返回它的2的x次冪(UInt64)。
intExp10(2);--10^2 接受一個數值類型的參數並返回它的10的x次冪(UInt64)。

-- 十一、取整函數
--->>>>>> 取整函數
-- 1.向下取整:floor(x[,N])
SELECT
floor(toFloat32(12.08098), 2), -- 12.08
floor(toFloat32(12.2323), 2), -- 12.23
floor(toFloat32(12.89788), -1), -- 10
floor(toFloat32(12.09590), 3), -- 12.095 (注意:如果按照正常的四捨五入,則應該是12.096,爲什麼呢?)
floor(toFloat32(12.0987), 3),-- 12.098
floor(10, 2); -- 10
-- 2.四捨五入:round(expression [, decimal_places])
-- 如果decimal_places=0,則取整數;
-- 如果>0,則將值舍入小數點右側;
-- 如果<0,則將小數點左側的值四捨五入。
SELECT
round(toFloat32(12.1234), 3),
round(toFloat32(12.0025), 3), -- 12.002(注意:爲什麼不是12.003呢?)
-- round函數只會最多保留三位有效數字
round(toFloat32(12.0025), 4), -- 12.002
round(toFloat32(12.0025002323), 100); -- 12.003
-- 示例:
SELECT
round(toFloat32(10 / 3)), -- 3
round(toFloat32(10 / 3), 2), -- 3.33
round(toFloat32(10.000/3), 3), -- 3.333
round(toFloat32(10.000/3), 6); -- 3.333
-- roundToExp2() 接受一個數字。如果數字小於1,則返回0。否則,它將數字向下舍入到最接近的(整個非負)2的x次冪。
SELECT
roundToExp2(12.0129), -- 8 = 2^3
roundToExp2(toFloat32(0.01)); -- 0.008
-- 3.向上取整:ceil(x[, N]) 或者 ceiling(x[, N])
SELECT
ceil(12.34343, 3), -- 12.344
ceil(toFloat64(12.34343), 3), -- 12.344
ceil(toFloat32(12.34343), 3), -- 12.344
ceil(12.0011, 3); -- 12.002


---十二、數組函數
--->>>>>> 數組函數
-- 1.數組非空判斷相關函數(真爲1,假爲0)
SELECT empty([]), empty([1,2,3]), notEmpty([1,2,3]), notEmpty([]);
-- 2.數組長度 length() 返回數組中的元素個數。 結果類型是UInt64。 該函數也適用於字符串。
SELECT
-- length(), -- 出現異常
-- length([true, false]), -- 異常
-- length([1,2,,4]), --出現異常!
length([]), -- 0
length(['a','b','c']), -- 3
length([1,2,3]); -- 3
-- 3.擴展判斷非空的部分函數如下:不接受任何參數並返回適當類型的空數組
SELECT
emptyArrayUInt8(), -- UInt8的空數組
emptyArrayUInt16(),
emptyArrayUInt32(),
emptyArrayUInt64(),
emptyArrayDate(),
emptyArrayDateTime(),
emptyArrayInt8(),
emptyArrayInt16(),
emptyArrayInt32(),
emptyArrayInt64();
-- 接受一個空數組並返回一個僅包含一個默認值元素的數組。(以下是部分示例)
SELECT
emptyArrayToSingle(emptyArrayInt32()), -- 0
emptyArrayToSingle(emptyArrayUInt32()), -- 0
emptyArrayToSingle(emptyArrayDate()), -- 0002-11-30
emptyArrayToSingle(emptyArrayDateTime()); --0002-11-30 08:00:00
-- 4.生成一個含有N個元素的數組,元素從0開始增長,步長尾1.
-- range(N) 返回從0到N-1的數字數組。 以防萬一,如果在數據塊中創建總長度超過100,000,000個元素的數組,則拋出異常
SELECT
range(10), -- [0,1,2,3,4,5,6,7,8,9]
range(2), -- [0,1]
-- range(5.5), -- 出現異常,N爲Int8的數據類型,正整數
-- range(-10), -- 出現異常,DB::Exception: Illegal type Int8 of argument of function range
range(1); -- 0
-- 5.新建一個數組的函數:array(x1,……) 類似於 直接[x1,……]
-- 注意:新建數組的每個元素的數據類型需保持一致性。
SELECT
array(1,2,2,3,4) AS "array()函數",
-- [1,'hello',3], -- 出現異常,DB::Exception: There is no supertype for types UInt8, String, UInt8 because some of them are String/FixedString and some of them are not (version 19.10.1.5 (official build))
[1,2,3,4] AS "[ ]";
-- 6.合併N個數組 arrayConcat(arrays) 合併參數中傳遞的所有數組。跟java的數組差不多的合併,不會自動去重,不會自動排序
SELECT
arrayConcat(array(1,2),array(2,3),array(4,5)), -- [1,2,2,3,4,5](第一種情況)
arrayConcat(array(1,1),array(2,2),array(3,3)), -- [1,1,2,2,3,3]
-- arrayConcat(array(1,2),['a','c'],array(3,3)), -- 出現異常,不能將不同類型的數組進行合併
arrayConcat(array(1,1),[2,3],array(4,5)); -- [1,1,2,3,4,5]
-- 7.從數組arr中獲取索引爲“n”的元素。
-- n必須是任何整數類型。 數組中的索引從一開始。 支持負索引。在這種情況下,它選擇從末尾開始編號的相應元素。例如,arr [-1]是數組中的最後一項。
-- 如果索引超出數組的邊界,則返回默認值(數字爲0,字符串爲空字符串等).
SELECT
arrayElement(array(10,20,3), 1), -- 10
arrayElement(array(1,20,3), 2), -- 20
arrayElement(array(1,2,30), 3), -- 30
arrayElement(array(10,20,3), 0), -- 0
arrayElement(array(10,20,3), -3), -- 10
arrayElement(array(10,20,3), -2), -- 20
arrayElement(array(10,20,3), -1);-- 3
-- 8.檢查在數組中是否含有此元素。has(arr, elem) 包含此元素則返回1,否則返回0
-- has() 檢查'arr'數組是否具有'elem'元素。 如果元素不在數組中,則返回0;如果在,則返回1。
-- hasAny(arr1, arr2) 返回1表示arr1和arr2存在交集。否則返回0.
--注意:特殊的定義:
-- ① “NULL”作爲數組中的元素值進行處理。
-- ② 忽略兩個數組中的元素值的順序
-- hasAll(set, subset) 檢查一個數組是否是另一個數組的子集。返回1,表示set包含subset中所有的元素
-- set – 具有一組元素的任何類型的數組。
-- subset – 任何類型的數組,其元素應該被測試爲set的子集。
-- 注意:特殊的定義:
-- ① 空數組是任何數組的子集。
-- ② “NULL”作爲數組中的元素值進行處理。
-- ③ 忽略兩個數組中的元素值的順序。
SELECT
has([1,2,3], 2), -- 1
has(array(1,2,3),2), -- 1
has([1,2,NULL], NULL), -- 1 (注意:null值的處理)
-- has([], 2), -- 出現異常,DB::Exception: Types of array and 2nd argument of function has must be identical up to nullability or numeric types or Enum and numeric type. Passed: Array(Nothing) and UInt8
has([1,2], 3); -- 0
SELECT
hasAll([], []), -- 1
hasAll([1,NULL,NULL], [NULL]), -- 1
hasAll([1,2,3], [1,2]), -- 1
hasAll([1,2,2,3], [2]), -- 1
hasAll(array(1,2,2,3), [2]), -- 1
hasAll([1,2,3], [4,5]); -- 0
-- 多重數組(如下的二維數組)。
SELECT hasAll([[1, 2], [3, 4]], [[1, 2], [3, 5]]); -- 0
SELECT
hasAny(array(1,2,3), array(1)), -- 1
hasAny(array(1,2,3), array(1,4,56,80)), -- 1
-- []與array()是一樣的含義,本質上是一直的。只不過[]更加簡便而已。
hasAny(array(), array()), -- 0
hasAny([],[]), -- 0
hasAny([1],[]), -- 0
-- 空數組跟null不是一樣的對象
hasAny([1,NULL],[]), -- 0
hasAny([1,NULL],[NULL,2]); -- 1


-- 9.返回數組指定元素的索引
-- indexOf(arr, x) 返回數組中第一個‘x’元素的索引(從1開始),如果‘x’元素不存在在數組中,則返回0。
SELECT indexOf(['one','two','three'], 'one'); -- 1
SELECT indexOf([1, 2, 4], 4); -- 3
SELECT
indexOf(['one','two','three'], 'one'), -- 1
indexOf(['one',NULL,NULL], NULL),-- 1返回第一個找到的元素的索引位置
indexOf([1, 2, 4], 4); -- 3
-- 數組元素的以第一個和最後一個元素。
SELECT length([12,3,4,4,4]);
SELECT array(12,22,31)[1];

WITH
[23,43,565,2,32,34] AS arr
SELECT
arr[1], -- 去除數組中的第一個元素
arr[length(arr)]; -- 提取元素中的最後一個元素

-- 10.計算數組中包含指定元素的個數
-- countEqual(arr, x) 返回數組中等於x的元素的個數。相當於arrayCount(elem - > elem = x,arr)。
-- 注意:null值將作爲單獨的元素值處理。
SELECT
countEqual([1, 2, 2, 2, 3, 4], 2), -- 3
countEqual([1, 2, NULL, NULL], NULL); -- 2

-- 11.arrayEnumerate(arr) 返回 Array [1, 2, 3, ..., length (arr) ] 此功能通常與ARRAY JOIN一起使用。它允許在應用ARRAY JOIN後爲每個數組計算一次。
SELECT arrayEnumerate([1,20,20,3]); -- [1,2,3,4]
SELECT arrayEnumerate(array(11,20,13)); -- [1,2,3]
SELECT arrayEnumerate(array(11,20,13,NULL)); -- [1,2,3,4] 注意:null也算是一個元素。
--arrayEnumerateUniq(arr) 返回與源數組大小相同的數組,其中每個元素表示與其下標對應的源數組元素在源數組中出現的次數
SELECT arrayEnumerateUniq([1,1,2,2]); -- [1,2]

-- 12.刪除數組的元素
-- arrayPopBack(array) 刪除數組array的最後一項
SELECT arrayPopBack(array(1,2,3,0)) AS res; -- [1,2,3]
-- arrayPopFront(array) 從數組中刪除第一項
SELECT arrayPopFront(array(0,1,2,3)) AS res; -- [1,2,3]

-- 13.添加數組的元素 arrayPushFront(array, single_value) single_value是單個值
SELECT arrayPushBack([1,2,3], 0) AS res; -- [1,2,3,0]
SELECT arrayPushFront([1,2,3], 0) AS res; -- [0,1,2,3]

-- 14.更改數組的長度 arrayResize(arr, size[, extender])
-- 如果arr的長度 > size,則會對arr截取size的長度;
-- 如果arr的長度 < size,則其餘位置用對應數據類型的默認值填充。
-- 注意:extender含義是擴展元素的值。如果沒有指定extender,則默認按照對應的數據類型的默認值進行賦值。否則按照extender進行填充。
SELECT arrayResize([1,2,3], 5); -- [1,2,3,0,0]
SELECT arrayResize([1,2,3], 2); -- [1,2]
SELECT arrayResize([1,2,3], 3); -- [1,2,3]
--↓↓↓ RuntimeException: Parse exception: ByteFragment{[[[1,2],[3,4],[5,6],[],[]]], start=0, len=25}
SELECT arrayResize([array(1,2),array(3,4),array(5,6)], 5);
SELECT arrayResize([1,2,3], 5, 12); -- [1,2,3,12,12]
SELECT arrayResize(['one','two','three'], 5); -- ['one','two','three','','']
SELECT arrayResize(['one','two','three'], 5, 'default'); -- ['one','two','three','default','default']

-- 15.截取數組的部分元素,得到一個新的子數組
-- arraySlice(array, offset[, length])
-- 解釋:
-- array: 數組,
-- offset – 數組的偏移。正值表示左側的偏移量,負值表示右側的縮進值。數組下標從1開始。
-- length - 子數組的長度。如果指定負值,則該函數返回[offset,array_length - length。如果省略該值,則該函數返回[offset,the_end_of_array]。
SELECT
arraySlice([1,2,3,4,5,6], 0, 3), -- 無返回值
arraySlice([1,2,NULL,5,6], 1, 3), -- [1,2,0]
arraySlice(['one','two',NULL], 1, 3), -- ['one','two','']
arraySlice([1,2,3,4,5,6], 1, 3); -- [1,2,3]

-- 16.數組排序:arraySort([func,] arr, ……)
-- 注意:如果在字符串數組中,''和NULL是需要特別對待的,''需要放在最前面,而NULL則是按順序存放到最後的。
-- arraySort是高階函數。您可以將lambda函數作爲第一個參數傳遞給它。在這種情況下,排序順序由lambda函數的調用結果決定。
SELECT
arraySort(['a','',NULL,'c','b']) AS hasNullempty1, --['','a','b','c',''] (第一個是'',最後一個''起始是NULL)
arraySort(array('ac','ab','bc','ad',NULL)) AS hasNull, -- ['ab','ac','ad','bc','']
arraySort(array('ac','','ab',NULL,'bc','ad',NULL)) AS hasNullempty2, -- ['','ab','ac','ad','bc','','']
arraySort([5,4,3,2,1]) AS numSorted,-- [1,2,3,4,5] (數字排序)
arraySort(['ca','bb','ac']) AS strSorted;-- ['ac','bb','ca'] (字符串排序)
SELECT
arraySort([NULL, 1, 3, NULL, 2]) AS sortedArr, -- [1,2,3,0,0]
arrayReverse(sortedArr) AS reverseSortdArr;-- [0,0,3,2,1]
-- 下面這種排序的實質,正數轉成負數,再在數學上比較升序排序。
SELECT arraySort(x -> -x, [1,2,3]) as res; -- [3,2,1] 降序:(高階函數用法)
SELECT arraySort((x) -> -x, [1,2,3]) as res; -- [3,2,1] 降序:(高階函數用法)
SELECT arraySort(x -> x, [5,4,3,1,2,3]) as res; -- [1,2,3,3,4,5] 升序:(高階函數用法)
SELECT arraySort((x) -> x, [5,4,3,1,2,3]) as res; -- [1,2,3,3,4,5] 升序:(高階函數用法)
-- arraySort(lambda, arr1, arr2)
SELECT arraySort((x, y) -> y, ['hello', 'world'], [2, 1]) as res; -- ['world','hello']
SELECT arraySort((x, y) -> -y, [0, 1, 2], [1, 2, 3]) as res; -- [2,1,0]
-- 再次提醒:NULL, NaN, Inf的排序順序:
-- 含義:
-- -Inf 是數組中的第一個。
-- NULL 是數組中的最後一個。
-- NaN 在NULL的前面。
-- Inf 在NaN的前面。
-- 出現異常:RuntimeException: Parse exception:
-- ByteFragment{[[-inf,-4,1,2,3,inf,nan,nan,NULL,NULL]], start=0, len=37}
SELECT arraySort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf]);

-- 17.數組翻轉:arrayReverse([func,] arr, ……)
-- 如果是NULL的話在排序的過程中,根據數組的數據類型進行默認值填充。
SELECT
arrayReverse(array('a','b','c',NULL)) AS hasOneNull, -- ['','c','b','a']
arrayReverse(array('ac','ab','bc','ad',NULL)) AS hasNull, -- ['','ad','bc','ab','ac']
--網格視圖: ['[NULL]','ad','bc','','ab','[NULL]','','ac'];文本視圖 :['','ad','bc','','ab','','','ac']
arrayReverse(array('ac','',NULL,'ab','','bc','ad',NULL)) AS hasNullEmpty,
arrayReverse(array(NULL, 3, NULL, 2, 1)),-- [1,2,0,3,0]
arrayReverse([1,2,3,4]);-- [4,3,2,1]

-- 18.數組排序並翻轉:arraySort([func,] arr, ...)
SELECT arrayReverseSort([1, 3, 3, 0]); -- [3,3,1,0]
SELECT arrayReverseSort(['hello', 'world', '!']); -- ['world','hello','!']
--RuntimeException: Parse exception: ByteFragment{[[inf,3,2,1,-4,-inf,nan,nan,NULL,NULL]], start=0, len=37}
SELECT arrayReverseSort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf]) as res;-- [inf,3,2,1,-4,-inf,nan,nan,NULL,NULL]
-- 下面的執行順序爲:
-- 1.首先,根據lambda函數的調用結果對源數組([1, 2, 3])進行排序。 結果是[3, 2, 1]。
-- 2.反轉上一步獲得的數組。 所以,最終的結果是[1, 2, 3]。
SELECT arrayReverseSort((x) -> -x, [1, 2, 3]) as res; -- [1,2,3]
SELECT arrayReverseSort((x) -> x, [1, 2, 3]) as res; -- [1,2,3]
-- 下面的執行順序爲:
-- 1.首先,根據lambda函數的調用結果對源數組(['hello','world'])進行排序。 其中,在第二個數組([2,1])中定義了源數組中相應元素的排序鍵。 所以,排序結果['world','hello']。
-- 2.反轉上一步驟中獲得的排序數組。 所以,最終的結果是['hello','world']。
SELECT arrayReverseSort((x, y) -> y, ['hello', 'world'], [2, 1]) as res;-- ['hello','world']
SELECT arrayReverseSort((x, y) -> -y, ['hello', 'world'], [2, 1]) as res;-- ['world','hello']
SELECT arrayReverseSort((x, y) -> x, ['hello', 'world'], [2, 1]) as res;-- ['world','hello']
--出現異常:Illegal type String of argument
--SELECT arrayReverseSort((x, y) -> -x, ['hello', 'world'], [2, 1]) as res;
SELECT arrayReverseSort((x, y) -> x, ['hello', 'world'], [1, 2]) as res;-- ['world','hello']

-- 19.統計數組中不重複元素的個數。arrayUniq(arr,……)
-- ① 如果傳遞一個參數,則計算數組中不同元素的數量。
-- ② 如果傳遞了多個參數,則它計算多個數組中相應位置的不同元素元組的數量
SELECT
arrayUniq([1,2,3]), -- 3
arrayUniq([1,2,2,2,3]); -- 3
SELECT
arrayUniq([1,2,3],[2,3,4]),
arrayUniq([1,2,2],[1,3,3]);

-- 20.數組的特殊功能:arrayJoin(arr) 這是一個非常有用的函數。
-- 解釋:此函數將數組作爲參數,並將該行在結果集中複製數組元素個數
SELECT arrayJoin([1, 2, 3] AS src) AS dst, 'Hello', src;
-- 每個元素擴大兩倍;
SELECT arrayJoin([1,2,3]) * 2;
SELECT arrayJoin([-1,-2,0,1,2]) * 2;
--出現異常: Illegal types Array(UInt8) and Array(UInt8) of arguments of function multiply
--SELECT multiply(array(1,2,3), 2);
SELECT multiply(arrayJoin([-1,-2,0,1,2]), 2);
-- 每個元素縮小兩倍
SELECT arrayJoin([-4,-2,0,2,4]) / 2;
SELECT divide(arrayJoin([-4,-2,0,2,4]) , 2);


-- 21.arrayDifference(arr)
-- 返回一個數組,其中包含所有相鄰元素對之間的差值
SELECT arrayDifference([1,2,3,4]);-- [0,1,1,1]
SELECT arrayDifference([1,3,10,50]);-- [0,2,7,40]


-- 22. arrayDistinct(arr)返回一個包含所有數組中不同元素的數組.
-- 類似於java的Set集合,對list集合進行去重。
SELECT arrayDistinct(array(1,2,3,4,4,4)); -- [1,2,3,4]
SELECT arrayDistinct([1,2,2,3,4,2,2,5,4,5]); -- [1,2,3,4,5]
SELECT arrayDistinct(array(0,1,NULL,3,4,4,4)); -- [0,1,3,4]
-- 數組去重統計元素個數
SELECT uniq(arrayJoin([1,2,3,6,3])); -- 4 表示數組去重後元素的個數
SELECT uniqArray([1,2,3,4,1,2,3,4]); -- 4 表示數組去重後元素的個數
-- 數組元素累計
SELECT sumArray([1,2,3,4,5]);-- 15
SELECT sum(arraySum([1,2,3,4,5])); -- 15


-- 23. arrayEnumerateDense(arr) 返回與源數組大小相同的數組,指示每個元素首次出現在源數組中的位置
SELECT
arrayEnumerateDense([10,20,20,10,30]) AS numArrEnumDense,-- [1,2,2,1,3]
-- [1,1,2,3,4,1,3,5,5]
arrayEnumerateDense([10,10,2,12,3,10,12,NULL,NULL]) as arrEnumDenseHasNull,
-- [1,2,1,1,2,3]
arrayEnumerateDense([10,20,10,10,20,30]) AS arrEnumDese2;

-- 24. arrayIntersect(arr,……) 返回所有數組元素的交集。
-- 如果arr的數目只有一個,則返回它本身;如果有多個數組,則返回所有數組中元素的交集。
SELECT
-- 注意:最後得到的數組元素的順序。(有什麼影響嗎?)
arrayIntersect(['one','two'],['one','two','three']) as uniStrArr1, -- ['two','one']
arrayIntersect(['aaa','bbb'],['bbb','aaa','three']) as uniStrArr2, -- ['bbb','aaa']
arrayIntersect([1,2],[1,2,3]) as uniArr1, -- [1,2]
arrayIntersect([1,2],[1,2,3],[2,3,4],[2,3,4]) as uniArr2; -- 2
SELECT
arrayIntersect([1,2], [3,4]), -- []
arrayIntersect([1,2]);-- [1,2]

-- 25.arrayReduce(agg_func, arr1, ...)
-- agg_func 爲聚合函數,傳入到數組當中。
-- 將聚合函數應用於數組並返回其結果.如果聚合函數具有多個參數,則此函數可應用於相同大小的多個數組。
SELECT
arrayReduce('max', [1,2,3]) AS minNum,--最大值 3
arrayReduce('min', [1,2,3]) AS maxNum,--最小值 1
arrayReduce('sum', [1,2,3]) AS sumNum;--求和 6

-- 十三、 字符串查分合並函數
--->>>>>> 字符串拆分合並函數
-- 1.splitByChar(separator, s) 將字符串以‘separator’拆分成多個子串。
-- ‘separator’必須爲僅包含一個字符的字符串常量。 返回拆分後的子串的數組。
-- 如果分隔符出現在字符串的開頭或結尾,或者如果有多個連續的分隔符,則將在對應位置填充空的子串。
SELECT splitByChar(',', 'hello,world!'); -- ['hello','world!']
--下面異常:Illegal separator for function splitByChar. Must be exactly one byte.
--SELECT splitByChar('or', 'hello,world!');

-- 2.splitByString(separator, s)
-- 與上面相同,但它使用多個字符的字符串作爲分隔符。 該字符串必須爲非空
SELECT splitByString('or','goodorniceorgreat'); -- ['good','nice','great']

-- 3.alphaTokens(s) 從範圍a-z和A-Z中選擇連續字節的子字符串。返回子字符串數組
SELECT alphaTokens('abca1abc'); -- ['abca','abc']
SELECT alphaTokens('abc1232abc2wer3rtty'); -- ['abc','abc','wer','rtty']

-- 4.數組元素合併函數:arrayStringConcat(arr[, sparator])
-- 使用separator將數組中列出的字符串拼接起來。
-- ‘separator’是一個可選參數:一個常量字符串,默認情況下設置爲空字符串。 返回拼接後的字符串
SELECT arrayStringConcat([1,2,3], '-'); -- 出現異常,要求數組必須是字符串string類型的元素
SELECT arrayStringConcat(['one','two','three']); -- onetwothree
SELECT arrayStringConcat(['one','two','three'], '-'); -- one-two-three
SELECT arrayStringConcat(['one','two','three',''], '-');-- one-two-three- 注意:NULL不能存在arr中


--十四、位操作符
--->>>>>> 位操作符
--位操作函數適用於UInt8,UInt16,UInt32,UInt64,Int8,Int16,Int32,Int64,Float32或Float64中的任何類型。
--結果類型是一個整數,其位數等於其參數的最大位。
--如果至少有一個參數爲有符數字,則結果爲有符數字。如果參數是浮點數,則將其強制轉換爲Int64。
SELECT
bitAnd(1,0), -- 0
bitAnd(1,1), -- 1
bitAnd(1,2), -- 0
bitAnd(-1,0), -- 0
bitAnd(-1,-2), -- -2
bitAnd(-10,-1), -- -10
bitOr(1,2), -- 3
bitOr(1,0), -- 1
bitOr(2,0), -- 2
bitOr(0,2); -- 2
SELECT bitXor(1, 2), bitXor(20, 15), bitNot(2);-- 3 27 253


--十五、Hash函數:可以用於將元素不可逆的僞隨機打亂。
-- 注意:僞隨機!
SELECT
-- 計算字符串的MD5值。( 如果您不需要一定使用MD5,請使用‘sipHash64’函數。)
halfMD5('HELLO WORLD!'),
halfMD5(12);
SELECT
MD5('drew-zero,78967');

SELECT
-- 爲任何類型的整數計算32位的哈希。 這是相對高效的非加密Hash函數
intHash32(1221232132132) AS intHash32,
-- 推薦:從任何類型的整數計算64位哈希碼。 它的工作速度比intHash32函數快。
intHash64(1221232132132) AS intHash64,
-- 計算任意數量字符串的CityHash64或使用特定實現的Hash函數計算任意數量其他類型的Hash。
cityHash64('username') AS cityHash64,
-- 1.使用sha1或者sha224加密的話,只能用於字符串
-- 2.字符串 需使用單引號。
SHA1('1232131') AS sha1,
SHA224('1232131') AS sha224,
SHA256('DREW-ZERO') AS sha256;

-- URLHash(url[, N]) 一種快速的非加密哈希函數,用於規範化的從URL獲得的字符串
-- 從一個字符串計算一個哈希,如果結尾存在尾隨符號/,?或#則忽略。 URLHash(s,N)
-- 計算URL層次結構中字符串到N級別的哈希值,如果末尾存在尾隨符號/,?或#則忽略。 URL的層級與URLHierarchy中的層級相同
-- 用處:此函數被用於Yandex.Metrica。
SELECT
URLHash('www.baidu.com'), -- 11390370829909720855
URLHash('www.baidu.com', 0), -- 11390370829909720855
--
URLHash('www.baidu.com', 1); -- 11160318154034397263

-- farmHash64(s) 計算字符串的FarmHash64。 接受一個String類型的參數。返回UInt64。
SELECT farmHash64('www.runoob.com'); -- 6668483584160323388

-- javaHash(s) 計算字符串的JavaHash。 接受一個String類型的參數。返回Int32。
SELECT javaHash('www.baidu.com'); -- 270263191

-- hiveHash(s) 計算字符串的HiveHash。 接受一個String類型的參數。返回Int32。 與JavaHash相同,但不會返回負數
SELECT hiveHash('www.baidu.com'); -- 270263191


--十六、隨機函數
--->>>>>> 隨機函數
-- 解釋:隨機函數使用非加密方式生成【僞隨機】數字。
-- ① 所有隨機函數都只接受一個參數或不接受任何參數。
-- ② 您可以向它傳遞任何類型的參數,但傳遞的參數將不會使用在任何隨機數生成過程中。
-- ③ 此參數的唯一目的是防止公共子表達式消除,以便在相同的查詢中使用相同的隨機函數生成不同的隨機數
-- rand() 函數:返回一個UInt32類型的隨機數字,所有UInt32類型的數字被生成的概率均相等。
-- rand64() 函數:返回一個UInt64類型的隨機數字,所有UInt64類型的數字被生成的概率均相等。
-- randConstant() 函數:返回一個UInt32類型的隨機數字,該函數不同之處在於僅爲每個數據塊參數一個隨機數。
SELECT
rand(), -- 1751687411
rand(10), -- 1124981728
rand64(),
rand64(10),
randConstant(),
randConstant();


-- 十七、編碼函數:
-- hex(), unhex(), UUIDStringToNum(str), UUIDNumToString(str),bitmaskToList(num) ...
-- 1.hex函數編碼
SELECT
-- 68656C6C6F20776F726C64212C68656C6C6F20636C69636B686F757365
hex('hello world!,hello clickhouse') AS hexStr,
hex(now()) AS hexDatetime, -- 5D414BA2
hex(toDate(now())) AS hexDate; --46BC

-- 2.接受包含36個字符的字符串,格式爲“123e4567-e89b-12d3-a456-426655440000”,並將其轉化爲FixedString(16)返回
SELECT UUIDStringToNum('123e4567-e89b-12d3-a456-426655440000');

-- 3. 接受一個整數。返回一個UInt64類型數組,其中包含一組2的冪列表,其列表中的所有值相加等於這個整數。數組中的數字按升序排列。
-- bitmaskToArray(num)
SELECT bitmaskToArray(10); -- [2,8]
SELECT bitmaskToArray(100); -- [4,32,64]

-- 4.接受一個整數。返回一個字符串,其中包含一組2的冪列表,其列表中的所有值相加等於這個整數。列表使用逗號分割,按升序排列。
-- bitmaskToList(num)
SELECT bitmaskToList(10); -- 2,8
SELECT bitmaskToList(100); -- 4,32,64
SELECT bitmaskToList(0); -- '' 空字符串


--十八、UUID函數
--->>>>>> UUID函數
-- 1.generateUUIDv4() 返回 UUID類型的值。
SELECT generateUUIDv4() as randomUUID; -- 隨機生成一個UUIDv4的字符串(b6940dfe-0dc9-4788-bac7-319d13235a2e)
SELECT replaceAll(toString(generateUUIDv4()), '-', '') AS replaceUUID; -- 9d1947ea4fcf450da5391feb6142cab6

-- 2.toUUID(s) 將string類型的值 轉換成UUID類型的值
SELECT toUUID('61f0c404-5cb3-11e7-907b-a6006ad3dba0') AS uuid;

-- 3.接受一個String類型的值,其中包含36個字符且格式爲xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
-- 將其轉換爲UUID的數值並以FixedString(16)將其返回。
SELECT
'612f3c40-5d3b-217e-707b-6a546a3d7b29' AS uuid, -- 612f3c40-5d3b-217e-707b-6a546a3d7b29
UUIDStringToNum(uuid) AS bytes; --a/<@];!~p{jTj={)

-- 4. UUIDNumToString() 接受一個FixedString(16)類型的值,返回其對應的String表現形式。
SELECT 'a/<@];!~p{jTj={)' AS bytes,
UUIDNumToString(toFixedString(bytes, 16)) AS uuid;

--- 二十、 URL函數:所有這些功能都不遵循RFC。它們被最大程度簡化以提高性能。
--- 什麼事RFC?
---- Request For Comments(RFC),是一系列以編號排定的文件。文件收集了有關互聯網相關信息,以及UNIX和互聯網社區的軟件文件。
-- 1. 截取函數:如果URL中沒有要截取的內容則返回空字符串。
SELECT protocol('http://www.baidu.com');-- http
SELECT protocol('https://www.baidu.com');-- https
SELECT protocol('www.baidu.com');-- ''
-- 獲取域名。
SELECT domain('http://www.baidu.com'); -- www.baidu.com
SELECT domain('https://www.google.com.cn'); -- www.google.com.cn
-- 返回域名並刪除第一個‘www.’
SELECT domainWithoutWWW('http://www.baidu.com');-- baidu.com
SELECT domainWithoutWWW('www.baidu.com');-- ''
-- 返回頂級域名。例如:.ru
SELECT topLevelDomain('http://www.runoob.com.cn'); -- cn
SELECT topLevelDomain('https://www.huse.edn'); -- edu
-- 返回“第一個有效子域名”
-- 如果頂級域名爲‘com’,‘net’,‘org’或者‘co’則第一個有效子域名爲二級域名。否則則返回三級域名
SELECT firstSignificantSubdomain('https://news.yandex.com.tr/'); -- yandex
-- 返回包含頂級域名與第一個有效子域名之間的內容(參閱上面內容)
SELECT cutToFirstSignificantSubdomain('https://news.yandex.com.tr/'); -- yandex.com.tr
-- 返回URL路徑
SELECT path('https://blog.csdn.net/u012111465/article/details/85250030');-- /u012111465/article/details/85250030
-- 與上面相同,但包括請求參數和fragment。
SELECT pathFull('https://clickhouse.yandex/#quick-start'); -- /#quick-start
-- 返回請求參數。例如:page=1&lr=213。請求參數不包含問號已經# 以及# 之後所有的內容。
SELECT queryString('http://www.baidu.com/?page=1&lr=234'); -- page=1&lr=234 (根據?確定)
SELECT queryString('http://www.baidu.com/page=1&lr=234'); -- ''
-- 返回URL的fragment標識。fragment不包含#。
SELECT fragment('https://clickhouse.yandex/#quick-start'); -- quick-start
-- 返回請求參數和fragment標識。例如:page=1#29390。
SELECT queryStringAndFragment('https://www.baidu.com/s?ie=utf-8&rsv_sug7=100#ei-ai'); -- ie=utf-8&rsv_sug7=100#ei-ai


-- 2. 刪除URL中的部分內容 (如果URL中不包含指定的部分,則URL不變。)
SELECT cutWWW('www.baidu.com');-- www.baidu.com
SELECT cutWWW('https://www.baidu.com');-- www.baidu.com
SELECT cutWWW('https://www.baidu.com');-- www.baidu.com
-- 刪除請求參數
SELECT cutQueryString('http://www.baidu.com/1?page=1'); -- http://www.baidu.com/1
-- 刪除fragment標識。#同樣也會被刪除。
SELECT cutFragment('http://www.baidu.com/#quick-demo'); -- http://www.baidu.com/
-- 刪除請求參數以及fragment標識。問號以及#也會被刪除。
SELECT cutQueryStringAndFragment('http://www.baidu.com/1?page=23#we'); -- http://www.baidu.com/1
-- cutURLParameter(URL, name) 刪除URL中名稱爲‘name’的參數。下面例子中的參數是:&之後,resv,name
SELECT cutURLParameter('http://www.baidu.com/1?page=1#erre&resv=23&name=user','resv');


--二十一、IP函數

 

--二十二、條件函數
SELECT IF(12 > 10 , 12, 20);
SELECT 12 > 10 ? 12 : 10;
SELECT if(greater(12, 10), 12, 10);

 

--二十三、操作符函數替換
-- clickhouse自帶的計算操作符函數(對接mybatis的時候不用將“<”之類的符號轉換成 “age1 <![CDATA[ < ]] 2>”)
-- 1.等於(注意函數名稱的大小,嚴格區分大小寫)
SELECT
equals('hello','hello'), -- 1
equals('ab','ba'); -- 0
-- 2.不等於
SELECT
notEquals('a','b'), -- 1
notEquals('a','a'), -- 0
notEquals(12, 12), -- 1
notEquals(12, 1010); -- 0
-- 3.大於( 如果前者大於後者,則返回1;否則返回0)
SELECT
greater(12, 10), -- 1
greater(10, 12), -- 0
greater(12, 12), -- 0
greater('b','a'), -- 1
greater('a','b'); -- 0
-- 3.1 擴展:提取兩者中最大的值
SELECT greatest(12,11); -- 12
-- 4.小於(如果前者小於後者,則返回1;否則返回0)
SELECT less(12,23); -- 1
SELECT less(120,23); -- 0
-- 5.大於或等於
SELECT greaterOrEquals(12,12); -- 1
SELECT greaterOrEquals(120,12); -- 1
-- 6.小於或等於
SELECT lessOrEquals(12,12); -- 1
SELECT lessOrEquals(12,129); -- 1
-- ===== String操作
-- *. a LIKE s
SELECT like('a', 'abcd'); -- 0
SELECT like('a', 'a'); -- 1

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