ClickHouse利用WITH语句实现的参数式SQL

ClickHouse的WITH语句功能比较强大,with一般有四种用法

WITH的使用方法

1.使用常量作为"变量"

eg:

WITH '2019-08-01 15:23:00' as ts_upper_bound
SELECT *
FROM hits
WHERE
    EventDate = toDate(ts_upper_bound) AND
    EventTime <= ts_upper_bound;

2.封装表达式

eg:

WITH sum(bytes) as exp_sum,formatReadableSize(exp_sum) as exp_,(partition='2022-02-04') as exp_filter
SELECT
    exp_sum,
    table
FROM system.parts
WHERE exp_filter
GROUP BY table
ORDER BY exp_sum;

3.使用标量子查询的结果

eg:

WITH
    (
        SELECT sum(bytes)
        FROM system.parts
        WHERE active
    ) AS total_disk_usage
SELECT
    (sum(bytes) / total_disk_usage) * 100 AS table_disk_usage,
    table
FROM system.parts
GROUP BY table
ORDER BY table_disk_usage DESC
LIMIT 10;

4.在子查询中重用表达式

eg:

WITH test1 AS (SELECT i + 1, j + 1 FROM test1)
SELECT * FROM test1;

参数式SQL写法

利用上文提到的WITH特性,我们可以将部分将部分需要代码传参的SQL抽象出来。

以ClickHouse的系统表 system.query_log表为例,query_log表为ch节点上执行过的sql日志表

假设我们有一个需求,需要按时间过滤出sql日志,且能按query内涉及到的表名模糊搜索。

WITH 
  /*常量列表*/
  $startTime as param_start_time,
  $endTime as param_end_time,
  '$table' as param_table,
  /*表达式*/
  (event_time >=param_start_time and event_time<param_end_time) as exp_time_filter,
  (toString(tables) like param_table) as exp_table_filter
SELECT
  query
FROM system.query_log
WHERE exp_time_filter AND exp_table_filter
  • 上述sql将参数分成了常量列表,以param开头;将涉及到参数的表达式封装,以exp开头。
    • param_start_time和param_end_time为时间范围,param_table为需要模糊搜索的表名
    • exp_time_filter拼接在where内用来过滤时间,exp_table_filter则是表名模糊搜索

使用这种sql写法,将sql的部分语句抽象成了“参数”与“函数”。所有的变量与表达式都写在WITH内,拼接SQL时只需处理WITH内的语句即可。

你可能感兴趣的:(ClickHouse,数据库,database,sql)