WITH語句已經成爲SQL語句必不可少的部分,Clickhouse目前的版本對CTE(Common Table Expression 公共表達式)的支持比較有限,相關的限制如下:
1.Recursive queries are not supported.
2.When subquery is used inside WITH section, it’s result should be scalar with exactly one row.
3.Expression’s results are not available in subqueries.
遞歸查詢不支持
在WITH部分的子查詢,只能返回一行數據
在子查詢中表達式的結果不可用。
WITH語句使用示例:
1.作爲變量:
Clickhouse> with 10 as start select number from system.numbers where number <5 limit 5;
WITH 10 AS start
SELECT number
FROM system.numbers
WHERE number < 5
LIMIT 5
┌─number─┐
│ 0 │
│ 1 │
│ 2 │
│ 3 │
│ 4 │
└────────┘
2.調用函數:
WITH sum(bytes) AS s
SELECT
formatReadableSize(s),
table
FROM system.parts
GROUP BY table
ORDER BY s ASC
┌─formatReadableSize(s)─┬─table──────┐
│ 2.59 KiB │ part_log │
│ 22.66 KiB │ trace_log │
│ 7.13 MiB │ metric_log │
│ 107.14 MiB │ t_dict │
│ 537.52 MiB │ visits_v1 │
│ 1.18 GiB │ hits_v1 │
└───────────────────────┴────────────┘
6 rows in set. Elapsed: 0.018 sec.
3.定義子查詢:
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
┌──────table_disk_usage─┬─table──────┐
│ 66.13563015490257 │ hits_v1 │
│ 29.31875240635302 │ visits_v1 │
│ 5.843957690326289 │ t_dict │
│ 0.3967229532123266 │ metric_log │
│ 0.0012069656728751568 │ trace_log │
│ 0.000137742753168703 │ part_log │
└───────────────────────┴────────────┘
6 rows in set. Elapsed: 0.019 sec.
4.在子查詢中重複使用WITH語句:
WITH round(database_disk_usage) AS database_disk_usage_v1
SELECT
database,
database_disk_usage,
database_disk_usage_v1
FROM
(
WITH
(
SELECT sum(data_uncompressed_bytes)
FROM system.columns
) AS total_bytes
SELECT
database,
(sum(data_uncompressed_bytes) / total_bytes) * 100 AS database_disk_usage
FROM system.columns
GROUP BY database
ORDER BY database_disk_usage DESC
)
┌─database─┬─database_disk_usage─┬─database_disk_usage_v1─┐
│ datasets │ 96.49589077926984 │ 96 │
│ system │ 3.5041092207301596 │ 4 │
└──────────┴─────────────────────┴────────────────────────┘
2 rows in set. Elapsed: 0.006 sec.
FROM 字句:
Clickhouse> select WatchID from hits_v1 limit 2;
SELECT WatchID
FROM hits_v1
LIMIT 2
┌─────────────WatchID─┐
│ 7043438415214026105 │
│ 4944118417295196513 │
└─────────────────────┘
2 rows in set. Elapsed: 0.056 sec.
Clickhouse> select max_watchid from(select max(WatchID) max_watchid from hits_v1);
SELECT max_watchid
FROM
(
SELECT max(WatchID) AS max_watchid
FROM hits_v1
)
┌─────────max_watchid─┐
│ 9223371678237104442 │
└─────────────────────┘
1 rows in set. Elapsed: 0.141 sec. Processed 8.87 million rows, 70.99 MB (63.04 million rows/s., 504.31 MB/s.)
Clickhouse> select number from numbers(4);
SELECT number
FROM numbers(4)
┌─number─┐
│ 0 │
│ 1 │
│ 2 │
│ 3 │
└────────┘
4 rows in set. Elapsed: 0.002 sec.
clickhouse中並沒有oracle中的DUAL表,但是可以用clickhouse.one替代:
示例:
Clickhouse> select 2 col union all select 3 from system.one FORMAT PrettyCompactNoEscapes;
SELECT 2 AS col
UNION ALL
SELECT 3
FROM system.one
FORMAT PrettyCompactNoEscapes
┌─col─┐
│ 2 │
└─────┘
┌─col─┐
│ 3 │
└─────┘
2 rows in set. Elapsed: 0.003 sec.
在FROM字句之後可以配合Final修飾符使用。可以配合CollapsingMergeTree和Versioned CollapsingMergeTree
等表引起進行查詢操作,以在查詢過程中強制合併,由於FINAL 修飾符會降低查詢性能,應該儘可能避免使用。
Clickhouse> select * from system.formats where name like '%Pretty%' format PrettyCompactNoEscapes;
SELECT *
FROM system.formats
WHERE name LIKE '%Pretty%'
FORMAT PrettyCompactNoEscapes
┌─name───────────────────┬─is_input─┬─is_output─┐
│ PrettyNoEscapes │ 0 │ 1 │
│ Pretty │ 0 │ 1 │
│ PrettySpace │ 0 │ 1 │
│ PrettyCompact │ 0 │ 1 │
│ PrettyCompactNoEscapes │ 0 │ 1 │
│ PrettySpaceNoEscapes │ 0 │ 1 │
└────────────────────────┴──────────┴───────────┘
Clickhouse> select * from system.formats where name like '%Pretty%' format PrettySpace;
SELECT *
FROM system.formats
WHERE name LIKE '%Pretty%'
FORMAT PrettySpace
name is_input is_output
PrettyNoEscapes 0 1
Pretty 0 1
PrettySpace 0 1
PrettyCompact 0 1
PrettyCompactNoEscapes 0 1
PrettySpaceNoEscapes 0 1
6 rows in set. Elapsed: 0.003 sec.
6 rows in set. Elapsed: 0.012 sec.
結論:
clickhouse的WITH語句相當受限制,並不好用。
參考:
https://clickhouse.tech/docs/en/sql-reference/statements/select/with/