DuckDB 的 ClickHouse SQL 宏
安装和加载
INSTALL chsql FROM community;
LOAD chsql;
示例
-- Use 100+ boring ClickHouse SQL function macros in DuckDB SQL queries.
D SELECT toString('world') AS hello, toInt8OrZero('world') AS zero;
┌─────────┬───────┐
│ hello │ zero │
│ varchar │ int64 │
├─────────┼───────┤
│ world │ 0 │
└─────────┴───────┘
D SELECT IPv4NumToString(167772161), IPv4StringToNum('10.0.0.1');
┌────────────────────────────┬─────────────────────────────┐
│ ipv4numtostring(167772161) │ ipv4stringtonum('10.0.0.1') │
│ varchar │ int32 │
├────────────────────────────┼─────────────────────────────┤
│ 10.0.0.1 │ 167772161 │
└────────────────────────────┴─────────────────────────────┘
-- Query a remote ClickHouse instance via HTTP/S API using multiple formats
D SELECT * FROM ch_scan("SELECT number * 100 FROM numbers(3)","https://play.clickhouse.com", format := 'Parquet');
┌───────────────────────┐
│ multiply(number, 100) │
│ varchar │
├───────────────────────┤
│ 0 │
│ 100 │
│ 200 │
└───────────────────────┘
-- Query the emulated system tables to explore columns, rows, types, storage, etc
D SELECT * FROM system.tables;
D SELECT * FROM system.columns;
D SELECT * FROM system.functions;
D SELECT * FROM system.uptime;
D SELECT * FROM system.disks;
┌──────────┬──────────────┬────────────┬─────────────┬──────────────────┬─────────────────┬─────────┬─────────────────────┬───────────────┬──────────────┬──────────────┬───────────────┬───────────┬───────────┬────────────┐
│ name │ path │ free_space │ total_space │ unreserved_space │ keep_free_space │ type │ object_storage_type │ metadata_type │ is_encrypted │ is_read_only │ is_write_once │ is_remote │ is_broken │ cache_path │
│ varchar │ varchar │ int64 │ int64 │ int64 │ int64 │ varchar │ varchar │ varchar │ boolean │ boolean │ boolean │ boolean │ boolean │ varchar │
├──────────┼──────────────┼────────────┼─────────────┼──────────────────┼─────────────────┼─────────┼─────────────────────┼───────────────┼──────────────┼──────────────┼───────────────┼───────────┼───────────┼────────────┤
│ localdb │ test.db │ 0 │ 262144 │ 0 │ 0 │ Local │ None │ None │ false │ false │ false │ false │ false │ │
│ memory │ NULL │ 0 │ 0 │ 0 │ 0 │ Local │ None │ None │ false │ false │ false │ false │ false │ │
│ testduck │ /tmp/duck.db │ 262144 │ 786432 │ 262144 │ 0 │ Local │ None │ None │ false │ false │ false │ false │ false │ │
└──────────┴──────────────┴────────────┴─────────────┴──────────────────┴─────────────────┴─────────┴─────────────────────┴───────────────┴──────────────┴──────────────┴───────────────┴───────────┴───────────┴────────────┘
关于 chsql
DuckDB ClickHouse SQL 扩展
DuckDB chsql 社区扩展实现了 100 多个常用的 ClickHouse SQL 宏、函数和助手,使使用者更容易在 OLAP 系统之间转换 ⭐
动机
DuckDB 是我们最喜欢的 OLAP 引擎,但 ClickHouse 拥有许多集成和用户。此扩展专门为 ClickHouse 用户提供。
✔ DuckDB SQL is awesome and full of great functions.<br>
✔ ClickHouse SQL is awesome and full of great functions.
✔ The DuckDB library is ~51M and modular. Can LOAD extensions.<br>
❌ The ClickHouse monolith is ~551M and growing. No extensions.
✔ DuckDB is open source and protected by a no-profit foundation.<br>
❌ ClickHouse is open core and controlled by for-profit corporation.
✔ DuckDB embedded is fast, mature and elegantly integrated in many languages.<br>
❌ chdb is still experimental, unstable and currently only supports Python.
扩展
- chsql_native 提供了一个本地 ClickHouse 客户端(二进制文件)和一个用于 ClickHouse Native 格式文件的读取器
法律声明
DuckDB ® 是 DuckDB 基金会的商标。ClickHouse® 是 ClickHouse Inc. 的商标。提及或描述的所有商标、服务标志和徽标均为其各自所有者的财产。使用任何第三方商标、品牌名称、产品名称和公司名称仅用于提供信息或作为模仿,并不暗示与各自所有者的认可、隶属关系或关联。
新增函数
function_name | 函数类型 | description | comment | examples |
---|---|---|---|---|
IPv4NumToString | macro | 将 IPv4 地址从数字格式转换为字符串格式 | NULL | [SELECT IPv4NumToString(2130706433);] |
IPv4StringToNum | macro | 将 IPv4 地址从字符串格式转换为数字格式 | NULL | [SELECT IPv4StringToNum('127.0.0.1');] |
arrayExists | macro | 检查数组中是否有任何元素满足条件 | NULL | [SELECT arrayExists(x -> x = 1, [1, 2, 3]);] |
arrayJoin | macro | 将数组展开为多行 | NULL | [SELECT arrayJoin([1, 2, 3]);] |
arrayMap | macro | 将函数应用于数组的每个元素 | NULL | [SELECT arrayMap(x -> x + 1, [1, 2, 3]);] |
bitCount | macro | 计算整数中设置的位的数量 | NULL | [SELECT bitCount(15);] |
ch_scan | table_macro | 使用 HTTP/s API 查询远程 ClickHouse 服务器 | 返回查询结果 | [SELECT * FROM ch_scan('SELECT version()','https://play.clickhouse.com', format := 'parquet');] |
domain | macro | 从 URL 中提取域名 | NULL | [SELECT domain('https://clickhouse.ac.cn/docs');] |
empty | macro | 检查字符串是否为空 | NULL | [SELECT empty('');] |
extractAllGroups | macro | 使用正则表达式从字符串中提取所有匹配的组 | NULL | [SELECT extractAllGroups('(\d+)', 'abc123');] |
formatDateTime | macro | 将 DateTime 值格式化为字符串 | NULL | [SELECT formatDateTime(now(), '%Y-%m-%d');] |
generateUUIDv4 | macro | 生成 UUID v4 值 | NULL | [SELECT generateUUIDv4();] |
ifNull | macro | 如果第一个参数不为 NULL,则返回第一个参数,否则返回第二个参数 | NULL | [SELECT ifNull(NULL, 'default');] |
intDiv | macro | 执行整数除法 | NULL | [SELECT intDiv(10, 3);] |
intDivOZero | macro | 执行整数除法,但如果除数为零,则返回零,而不是引发错误 | NULL | [SELECT intDivOZero(10, 0);] |
intDivOrNull | macro | 执行整数除法,但如果除数为零,则返回 NULL,而不是引发错误 | NULL | [SELECT intDivOrNull(10, 0);] |
leftPad | macro | 在字符串的左侧填充到指定的长度 | NULL | [SELECT leftPad('abc', 5, '*');] |
lengthUTF8 | macro | 返回字符串的 UTF-8 字符长度 | NULL | [SELECT lengthUTF8('Привет');] |
match | macro | 对字符串执行正则表达式匹配 | NULL | [SELECT match('abc123', '\d+');] |
minus | macro | 执行两个数字的减法 | NULL | [SELECT minus(5, 3);] |
modulo | macro | 计算除法的余数(模数) | NULL | [SELECT modulo(10, 3);] |
moduloOrZero | macro | 计算模数,但除数为零时返回零,而不是错误 | NULL | [SELECT moduloOrZero(10, 0);] |
notEmpty | macro | 检查字符串是否不为空 | NULL | [SELECT notEmpty('abc');] |
numbers | table_macro | 生成从 0 开始的数字序列 | 返回一个包含单列 (UInt64) 的表 | [SELECT * FROM numbers(10);] |
parseURL | macro | 提取 URL 的各个部分 | NULL | [SELECT parseURL('https://clickhouse.ac.cn', 'host');] |
path | macro | 从 URL 中提取路径 | NULL | [SELECT path('https://clickhouse.ac.cn/docs');] |
plus | macro | 执行两个数字的加法 | NULL | [SELECT plus(5, 3);] |
protocol | macro | 从 URL 中提取协议 | NULL | [SELECT protocol('https://clickhouse.ac.cn');] |
read_parquet_mergetree | table | 使用主排序键合并 parquet 文件以进行快速范围查询 | experimental | [COPY (SELECT * FROM read_parquet_mergetree(['/folder/*.parquet'], 'sortkey') TO 'sorted.parquet';] |
rightPad | macro | 在字符串的右侧填充到指定的长度 | NULL | [SELECT rightPad('abc', 5, '*');] |
splitByChar | macro | 按给定的字符分割字符串 | NULL | [SELECT splitByChar(',', 'a,b,c');] |
toDayOfMonth | macro | 从日期中提取月份中的日 | NULL | [SELECT toDayOfMonth('2023-09-10');] |
toFixedString | macro | 将值转换为固定长度的字符串 | NULL | [SELECT toFixedString('abc', 5);] |
toFloat | macro | 将值转换为浮点数 | NULL | [SELECT toFloat('123.45');] |
toFloatOrNull | macro | 将值转换为浮点数,如果转换失败则返回 NULL | NULL | [SELECT toFloatOrNull('abc');] |
toFloatOrZero | macro | 将值转换为浮点数,如果转换失败则返回零 | NULL | [SELECT toFloatOrZero('abc');] |
toHour | macro | 从 DateTime 值中提取小时 | NULL | [SELECT toHour(now());] |
toInt128 | macro | 将值转换为 128 位整数 | NULL | [SELECT toInt128('123456789012345678901234567890');] |
toInt128OrNull | macro | 转换为 128 位整数,失败则返回 NULL | NULL | [SELECT toInt128OrNull('abc');] |
toInt128OrZero | macro | 转换为 128 位整数,失败则返回零 | NULL | [SELECT toInt128OrZero('abc');] |
toInt16 | macro | 将值转换为 16 位整数 | NULL | [SELECT toInt16('123');] |
toInt16OrNull | macro | 转换为 16 位整数,失败则返回 NULL | NULL | [SELECT toInt16OrNull('abc');] |
toInt16OrZero | macro | 转换为 16 位整数,失败则返回零 | NULL | [SELECT toInt16OrZero('abc');] |
toInt256 | macro | 将值转换为 256 位整数 | NULL | [SELECT toInt256('12345678901234567890123456789012345678901234567890123456789012345678901234567890');] |
toInt256OrNull | macro | 转换为 256 位整数,失败则返回 NULL | NULL | [SELECT toInt256OrNull('abc');] |
toInt256OrZero | macro | 转换为 256 位整数,失败则返回零 | NULL | [SELECT toInt256OrZero('abc');] |
toInt32 | macro | 将值转换为 32 位整数 | NULL | [SELECT toInt32('123');] |
toInt32OrNull | macro | 转换为 32 位整数,失败则返回 NULL | NULL | [SELECT toInt32OrNull('abc');] |
toInt32OrZero | macro | 转换为 32 位整数,失败则返回零 | NULL | [SELECT toInt32OrZero('abc');] |
toInt64 | macro | 将值转换为 64 位整数 | NULL | [SELECT toInt64('123');] |
toInt64OrNull | macro | 转换为 64 位整数,失败则返回 NULL | NULL | [SELECT toInt64OrNull('abc');] |
toInt64OrZero | macro | 转换为 64 位整数,失败则返回零 | NULL | [SELECT toInt64OrZero('abc');] |
toInt8 | macro | 将值转换为 8 位整数 | NULL | [SELECT toInt8('123');] |
toInt8OrNull | macro | 转换为 8 位整数,失败则返回 NULL | NULL | [SELECT toInt8OrNull('abc');] |
toInt8OrZero | macro | 转换为 8 位整数,失败则返回零 | NULL | [SELECT toInt8OrZero('abc');] |
toMinute | macro | 从 DateTime 值中提取分钟 | NULL | [SELECT toMinute(now());] |
toMonth | macro | 从 Date 值中提取月份 | NULL | [SELECT toMonth('2023-09-10');] |
toSecond | macro | 从 DateTime 值中提取秒 | NULL | [SELECT toSecond(now());] |
toString | macro | 将值转换为字符串 | NULL | [SELECT toString(123);] |
toUInt16 | macro | 将值转换为无符号 16 位整数 | NULL | [SELECT toUInt16('123');] |
toUInt16OrNull | macro | 转换为无符号 16 位整数,失败则返回 NULL | NULL | [SELECT toUInt16OrNull('abc');] |
toUInt16OrZero | macro | 转换为无符号 16 位整数,失败则返回零 | NULL | [SELECT toUInt16OrZero('abc');] |
toUInt32 | macro | 将值转换为无符号 32 位整数 | NULL | [SELECT toUInt32('123');] |
toUInt32OrNull | macro | 转换为无符号 32 位整数,失败则返回 NULL | NULL | [SELECT toUInt32OrNull('abc');] |
toUInt32OrZero | macro | 转换为无符号 32 位整数,失败则返回零 | NULL | [SELECT toUInt32OrZero('abc');] |
toUInt64 | macro | 将值转换为无符号 64 位整数 | NULL | [SELECT toUInt64('123');] |
toUInt64OrNull | macro | 转换为无符号 64 位整数,失败则返回 NULL | NULL | [SELECT toUInt64OrNull('abc');] |
toUInt64OrZero | macro | 转换为无符号 64 位整数,失败则返回零 | NULL | [SELECT toUInt64OrZero('abc');] |
toUInt8 | macro | 将值转换为无符号 8 位整数 | NULL | [SELECT toUInt8('123');] |
toUInt8OrNull | macro | 转换为无符号 8 位整数,失败则返回 NULL | NULL | [SELECT toUInt8OrNull('abc');] |
toUInt8OrZero | macro | 转换为无符号 8 位整数,失败则返回零 | NULL | [SELECT toUInt8OrZero('abc');] |
toYYYYMM | macro | 将 Date 格式化为 'YYYYMM' 字符串格式 | NULL | [SELECT toYYYYMM('2023-09-10');] |
toYYYYMMDD | macro | 将 Date 格式化为 'YYYYMMDD' 字符串格式 | NULL | [SELECT toYYYYMMDD('2023-09-10');] |
toYYYYMMDDhhmmss | macro | 将 DateTime 格式化为 'YYYYMMDDhhmmss' 字符串格式 | NULL | [SELECT toYYYYMMDDhhmmss(now());] |
toYear | macro | 从 Date 或 DateTime 值中提取年份 | NULL | [SELECT toYear('2023-09-10');] |
topLevelDomain | macro | 从 URL 中提取顶级域名 (TLD) | NULL | [SELECT topLevelDomain('https://example.com');] |
tupleConcat | macro | 将两个元组连接成一个元组 | NULL | [SELECT tupleConcat((1, 'a'), (2, 'b'));] |
tupleDivide | macro | 执行两个元组之间的元素级除法 | NULL | [SELECT tupleDivide((10, 20), (2, 5));] |
tupleDivideByNumber | macro | 将元组的每个元素除以一个数字 | NULL | [SELECT tupleDivideByNumber((10, 20), 2);] |
tupleIntDiv | macro | 执行两个元组之间的元素级整数除法 | NULL | [SELECT tupleIntDiv((10, 20), (3, 4));] |
tupleIntDivByNumber | macro | 将元组的每个元素除以一个数字(整数除法) | NULL | [SELECT tupleIntDivByNumber((10, 20), 3);] |
tupleMinus | macro | 执行两个元组之间的元素级减法 | NULL | [SELECT tupleMinus((10, 20), (5, 3));] |
tupleModulo | macro | 执行两个元组之间的元素级模运算 | NULL | [SELECT tupleModulo((10, 20), (3, 6));] |
tupleModuloByNumber | macro | 计算元组的每个元素除以一个数字的模 | NULL | [SELECT tupleModuloByNumber((10, 20), 3);] |
tupleMultiply | macro | 执行两个元组之间的元素级乘法 | NULL | [SELECT tupleMultiply((10, 20), (2, 5));] |
tupleMultiplyByNumber | macro | 将元组的每个元素乘以一个数字 | NULL | [SELECT tupleMultiplyByNumber((10, 20), 3);] |
tuplePlus | macro | 执行两个元组之间的元素级加法 | NULL | [SELECT tuplePlus((1, 2), (3, 4));] |
url | table_macro | 使用指定的格式对远程 URL 执行查询 | 支持 JSON, CSV, PARQUET, TEXT, BLOB | [SELECT * FROM url('https://urleng.com/test','JSON');] |
JSONExtract | macro | 基于 JSON 对象中的键提取 JSON 数据 | NULL | [SELECT JSONExtract(json_column, 'user.name');] |
JSONExtractString | macro | 从 JSON 对象中提取 JSON 数据作为 VARCHAR | NULL | [SELECT JSONExtractString(json_column, 'user.email');] |
JSONExtractUInt | macro | 从 JSON 对象中提取 JSON 数据作为无符号整数 | NULL | [SELECT JSONExtractUInt(json_column, 'user.age');] |
JSONExtractInt | macro | 从 JSON 对象中提取 JSON 数据作为 32 位整数 | NULL | [SELECT JSONExtractInt(json_column, 'user.balance');] |
JSONExtractFloat | macro | 从 JSON 对象中提取 JSON 数据作为 double | NULL | [SELECT JSONExtractFloat(json_column, 'user.score');] |
JSONExtractRaw | macro | 基于 JSON 对象中的键提取原始 JSON 数据 | NULL | [SELECT JSONExtractRaw(json_column, 'user.address');] |
JSONHas | macro | 检查 JSON 键是否存在且不为 null | NULL | [SELECT JSONHas(json_column, 'user.active');] |
JSONLength | macro | 返回 JSON 数组的长度 | NULL | [SELECT JSONLength(json_column, 'items');] |
JSONType | macro | 确定给定路径上的 JSON 元素的类型 | NULL | [SELECT JSONType(json_column, 'user.data');] |
JSONExtractKeys | macro | 从 JSON 对象中提取键 | NULL | [SELECT JSONExtractKeys(json_column);] |
JSONExtractValues | macro | 从 JSON 对象中提取所有值作为文本 | NULL | [SELECT JSONExtractValues(json_column);] |
equals | macro | 检查两个值是否相等 | NULL | [SELECT equals(column_a, column_b);] |
notEquals | macro | 检查两个值是否不相等 | NULL | [SELECT notEquals(column_a, column_b);] |
less | macro | 检查一个值是否小于另一个值 | NULL | [SELECT less(column_a, column_b);] |
greater | macro | 检查一个值是否大于另一个值 | NULL | [SELECT greater(column_a, column_b);] |
lessOrEquals | macro | 检查一个值是否小于或等于另一个值 | NULL | [SELECT lessOrEquals(column_a, column_b);] |
greaterOrEquals | macro | 检查一个值是否大于或等于另一个值 | NULL | [SELECT greaterOrEquals(column_a, column_b);] |
dictGet | macro | 从 VARIABLE 字符串或 MAP 中检索属性 | NULL | [SELECT dictGet('dictionary_name', 'attribute');] |
system_databases | table | NULL | NULL | NULL |
uptime | 标量 | NULL | NULL | NULL |
url_flock | table | NULL | NULL | NULL |
chsql | 标量 | NULL | NULL | NULL |
system_functions | table | NULL | NULL | NULL |
system_columns | table | NULL | NULL | NULL |
chsql_openssl_version | 标量 | NULL | NULL | NULL |
system_disks | table | NULL | NULL | NULL |
system_tables | table | NULL | NULL | NULL |