CTE(Common Table Expressions,公用表表达式)功能支持通过 WITH 子句定义一个或多个临时结果集(即公用表),这些结果集可以在同一个查询的后续部分中被多次引用。CTE 提供了一种清晰的方式来构建复杂的查询,使 SQL 代码更易读和维护。
注意:该功能从 V2.0.9-beta 版本开始提供。
CTE 的简化 SQL 语法如下:
with_clause: WITH cte_name [(col_name [, col_name] ...)] AS (subquery) [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
WITH 子句中定义一个或多个 CTE,且 CTE 之间可以嵌套引用(但不能前向引用,即不能使用尚未定义的 CTE)。Explain 或 ExplainAnalyze,但不支持对 CTE 定义中的 subquery 进行 Explain 或 ExplainAnalyze。subquery 输出列个数一致,否则报错。基于示例数据 中的表 table1 和 table2作为源表:
WITH cte1 AS (SELECT device_id, temperature FROM table1 WHERE temperature IS NOT NULL), cte2 AS (SELECT device_id, humidity FROM table2 WHERE humidity IS NOT NULL) SELECT * FROM cte1 join cte2 on cte1.device_id = cte2.device_id limit 10;
执行结果
+---------+-----------+---------+--------+ |device_id|temperature|device_id|humidity| +---------+-----------+---------+--------+ | 100| 90.0| 100| 45.1| | 100| 90.0| 100| 35.2| | 100| 90.0| 100| 35.1| | 100| 85.0| 100| 45.1| | 100| 85.0| 100| 35.2| | 100| 85.0| 100| 35.1| | 100| 85.0| 100| 45.1| | 100| 85.0| 100| 35.2| | 100| 85.0| 100| 35.1| | 100| 88.0| 100| 45.1| +---------+-----------+---------+--------+ Total line number = 10 It costs 0.075s
WITH table1 AS (SELECT time, device_id, temperature FROM table1 WHERE temperature IS NOT NULL) SELECT * FROM table1 limit 5;
执行结果
+-----------------------------+---------+-----------+ | time|device_id|temperature| +-----------------------------+---------+-----------+ |2024-11-30T09:30:00.000+08:00| 101| 90.0| |2024-11-30T14:30:00.000+08:00| 101| 90.0| |2024-11-29T10:00:00.000+08:00| 101| 85.0| |2024-11-27T16:39:00.000+08:00| 101| 85.0| |2024-11-27T16:40:00.000+08:00| 101| 85.0| +-----------------------------+---------+-----------+ Total line number = 5 It costs 0.103s
WITH table1 AS (select device_id, temperature from table1 WHERE temperature IS NOT NULL), cte1 AS (select device_id, temperature from table2 WHERE temperature IS NOT NULL), table2 AS (select temperature from table1), cte2 AS (SELECT temperature FROM table1) SELECT * FROM table2;
执行结果
+-----------+ |temperature| +-----------+ | 90.0| | 90.0| | 85.0| | 85.0| | 85.0| | 85.0| | 90.0| | 85.0| | 85.0| | 88.0| | 90.0| | 90.0| +-----------+ Total line number = 12 It costs 0.050s
WITH cte2 AS (SELECT temperature FROM cte1), cte1 AS (select device_id, temperature from table1) SELECT * FROM cte2;
错误信息
Msg: org.apache.iotdb.jdbc.IoTDBSQLException: 550: Table 'database1.cte1' does not exist.
WITH cte AS (select device_id, temperature from table1 WHERE temperature IS NOT NULL) SELECT * FROM cte WHERE temperature > (SELECT avg(temperature ) FROM cte);
执行结果
+---------+-----------+ |device_id|temperature| +---------+-----------+ | 101| 90.0| | 101| 90.0| | 100| 90.0| | 100| 88.0| | 100| 90.0| | 100| 90.0| +---------+-----------+ Total line number = 6 It costs 0.241s
EXPLAIN WITH cte AS (SELECT * FROM table1) SELECT * FROM cte;
执行结果
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | distribution plan| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ | | │OutputNode-7 │ | | │OutputColumns-[time, region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time] │ | | │OutputSymbols: [time, region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time]│ | | └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ | | │ | | │ | | ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ | | │Collect-42 │ | | │OutputSymbols: [time, region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time]│ | | └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ | | ┌───────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┐ | | │ │ | | ┌───────────┐ ┌───────────┐ | | │Exchange-49│ │Exchange-50│ | | └───────────┘ └───────────┘ | | │ │ | | │ │ | |┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐| |│DeviceTableScanNode-41 │ │DeviceTableScanNode-40 │| |│QualifiedTableName: database1.table1 │ │QualifiedTableName: database1.table1 │| |│OutputSymbols: [time, region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time]│ │OutputSymbols: [time, region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time]│| |│DeviceNumber: 3 │ │DeviceNumber: 3 │| |│ScanOrder: ASC │ │ScanOrder: ASC │| |│PushDownOffset: 0 │ │PushDownOffset: 0 │| |│PushDownLimit: 0 │ │PushDownLimit: 0 │| |│PushDownLimitToEachDevice: false │ │PushDownLimitToEachDevice: false │| |│RegionId: 2 │ │RegionId: 1 │| |└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Total line number = 29 It costs 0.065s
WITH cte AS (EXPLAIN SELECT * FROM table1) SELECT * FROM cte;
错误信息
Msg: org.apache.iotdb.jdbc.IoTDBSQLException: 700: line 1:14: mismatched input 'EXPLAIN'. Expecting: <query>