子查询(Subquery)
出现在一个select
语句之内的select
语句被称为子查询
。IoTDB支持标量子查询
,列子查询
和表子查询
。
不同类型的子查询在select
语句内部出现的位置是不同的,下面是 select
语句的语法定义:
selectClause
intoClause?
fromClause
whereClause?
specialClause?
由于对子查询分类时,涉及到对结果集列数的判定,我们统一约定:在计算结果集列数时,Time
列和Device
列不计入在内。
示例如下:
SQL1:
select count(*) from root.ln.wf01.* align by device
结果集1:
+-----------------+------------------+-------------+---------+
| Device|count(temperature)|count(status)|count(id)|
+-----------------+------------------+-------------+---------+
|root.ln.wf01.wt01| 1| 0| null|
|root.ln.wf01.wt02| 6| 14| null|
|root.ln.wf01.wt03| null| 2| 2|
|root.ln.wf01.wt04| 2| 1| null|
|root.ln.wf01.wt05| 2| 1| null|
+-----------------+------------------+-------------+---------+
SQL2:
select a,b from root.sg
结果集2:
+-----------------------------+---------+---------+
| Time|root.sg.a|root.sg.b|
+-----------------------------+---------+---------+
|2021-11-09T10:22:10.521+08:00| 1.0| 2.0|
|2021-11-09T10:22:17.231+08:00| 2.0| 3.0|
|2021-11-09T10:22:22.815+08:00| 3.0| 4.0|
|2021-11-17T10:21:58.790+08:00| 5.0| null|
+-----------------------------+---------+---------+
在上述示例中,我们认为结果集1是5行3列(Device
列不计入),结果集2是4行2列(Time
列不计入)。
标量子查询
标量子查询
指结果集为一行一列的子查询,允许出现在select
子句和where
子句中。
作为标量子查询
出现在另一个查询中需要满足下述条件:
结果集为一行一列
是非相关子查询,即子查询不会引用父查询
是聚合查询或聚合查询嵌套表达式
没有
specialClause
子句结果集数据类型为数值类型,即不是
Boolean
和Text
类型
SQL语法
使用标量子查询
时,您需要遵循以下限制:
将子查询放在一对英文圆括号中。
在
select
子句中出现时,标量子查询
可以作为表达式的一部分,但是表达式不能只包含标量子查询
在
where
子句中出现时,标量子查询
只能作为比较操作符的右操作数
详细说明请参考示例。
在select
子句中出现时,语法定义如下:
selectClause
: SELECT (LAST | topClause)? resultColumn (COMMA resultColumn)*
;
resultColumn
: expression (AS ID)?
;
expression
: LR_BRACKET unaryInBracket=expression RR_BRACKET
| (PLUS | MINUS) unaryAfterSign=expression
| (leftExpression=expression | scalarSubqueryClause) (STAR | DIV | MOD) rightExpression=expression
| leftExpression=expression (PLUS | MINUS) (rightExpression=expression | scalarSubqueryClause)
| functionName LR_BRACKET expression (COMMA expression)* functionAttribute* RR_BRACKET
| suffixPath
| constant
;
scalarSubqueryClause
: LR_BRACKET selectClause fromClause whereClause? RR_BRACKET
在where
子句中出现时,语法定义如下
whereClause
: WHERE (orExpression | indexPredicateClause)
;
orExpression
: andExpression (OPERATOR_OR andExpression)*
;
andExpression
: predicate (OPERATOR_AND predicate)*
;
predicate
: (TIME | TIMESTAMP | suffixPath | fullPath) comparisonOperator (constant | scalarSubqueryClause)
| (TIME | TIMESTAMP | suffixPath | fullPath) inClause
| OPERATOR_NOT? LR_BRACKET orExpression RR_BRACKET
| (suffixPath | fullPath) (REGEXP | LIKE) STRING_LITERAL
;
scalarSubqueryClause
: LR_BRACKET selectClause fromClause whereClause? RR_BRACKET
示例
在select
子句中使用
SQL:
select (select count(status) from root.ln.wf01.wt01) + count(a) from root.sg ;
结果集:
+-----------------------------------------------------------------------+
|select (select count(status) from root.ln.wf01.wt01) + count(root.sg.a)|
+-----------------------------------------------------------------------+
| 10084.0|
+-----------------------------------------------------------------------+
在where
子句中使用
SQL:
select count(b) from root.sg where a > (select count(a) from root.sg)
结果集:
+----------------+
|count(root.sg.b)|
+----------------+
| 0|
+----------------+
列子查询
列子查询
指结果集为一列N行(N>=1)的子查询,允许出现在另一个查询的where
子句中,与谓词in
配合使用。
作为列子查询
出现在另一个查询的where
子句中的查询需要满足下述条件:
结果集为一列N行(N>=1)
是非相关子查询,即子查询不会引用父查询
没有
intoClause
子句属于示例中出现的查询类型
SQL语法
使用列子查询
时,您需要遵循以下限制:
将子查询放在一对英文圆括号中。
在
where
子句中出现时,列子查询
只能作为in
的右操作数
详细说明请参考示例。
在where
子句中出现时,语法定义如下:
predicate
: (TIME | TIMESTAMP | suffixPath | fullPath) comparisonOperator constant
| (TIME | TIMESTAMP | suffixPath | fullPath) inClause
| OPERATOR_NOT? LR_BRACKET orExpression RR_BRACKET
| (suffixPath | fullPath) (REGEXP | LIKE) STRING_LITERAL
;
inClause
: OPERATOR_NOT? OPERATOR_IN (LR_BRACKET constant (COMMA constant)* RR_BRACKET | columnSubqueryClause)
;
columnSubqueryClause:
: LR_BRACKET selectClause fromClause whereClause? specialClause? RR_BRACKET
示例
注意,除了下述类型的查询,其余类型的查询(如LAST
查询)都不被支持。
原始序列查询作为子查询
select a
from root.sg
where a in (select a from root.sg1)
时间序列生成函数查询(UDF查询)作为子查询
select a
from root.sg
where a in (select sin(a) from root.sg1)
嵌套表达式查询作为子查询
select a
from root.sg
where a in (select ((a + 1) * 2 - 1) % 2 + 1.5 from root.sg1)
select a
from root.sg
where a in (select sin(a + sin(a + sin(b))) from root.sg1)
Fill查询作为子查询
select a
from root.sg
where a in (select a from root.sg1 where time = 10 fill(float [linear, 1ms, 1ms]))
Group By查询作为子查询
select a
from root.sg
where a in (select avg(a) from root.sg1 group by ([1, 5), 1ms))
Group By Fill查询作为子查询
select a
from root.sg
where a in (select avg(a) from root.sg1 group by ([1, 10),1ms) fill (float[PREVIOUS]))
表子查询
表子查询
指结果集为N行N列(N>=1)的子查询,允许出现在from
子句中。
作为表子查询
出现在另一个查询的from
子句中的查询需要满足下述条件:
是非相关子查询,即子查询不会引用父查询
SQL语法
使用表子查询
时,您需要遵循以下限制:
将子查询放在一对英文圆括号中。
子查询结果必须使用
as
取别名,请遵循as
取别名的语法规范,使用''
,具体方式请参考示例。如果父查询的
from
子句里同时出现子查询和prefixPath
,那么prefixPath
也需要通过as
取别名,from子句中出现的别名不能重复,子查询内部的as
别名也不能重复。
fromClause
的语法定义如下
fromClause
: FROM prefix (COMMA prefix)*
;
prefix
: prefixPath (AS ID)?
| LR_BRACKET selectStatement RR_BRACKET AS ID
prefixPath
: ROOT (DOT nodeName)*
;
注意:由于antlr语法定义的限制,prefixPath强制使用as取别名的情况是通过逻辑代码来检查的,这一点没有在上述语法定义中体现出来,您可以结合示例进行理解。
您可以通过形如tableName.columnName
的方式进行索引来获取表子查询结果集的列,有以下几点需要注意:
tableName.columnName
整体需要放在一对''
中
tableName是
as
语句中指定的别名,columnName是子查询内部结果列的列名在子查询内部,结果集的列名可以是原生列名,也可以使用别名,我们强烈建议您在子查询内部对结果集使用
as
取别名,在一个子查询内部别名不能重复。父查询结果集对应列的列名即为tableName.columnName,也可以通过
as
取别名。
示例
原始序列查询作为子查询
SQL1:
select 'table1.column1' from (select a as column1 from root.sg) as 'table1'
结果集1:
+-----------------------------+--------------+
| Time|table1.column1|
+-----------------------------+--------------+
|2021-11-09T10:22:10.521+08:00| 1.0|
|2021-11-09T10:22:17.231+08:00| 2.0|
|2021-11-09T10:22:22.815+08:00| 3.0|
|2021-11-17T10:21:58.790+08:00| 5.0|
+-----------------------------+--------------+
SQL2:
select 'table1.column1', 'table2.b' from (select a as column1 from root.sg) as 'table1', root.sg as 'table2'
结果集2
+-----------------------------+--------------+--------+
| Time|table1.column1|table2.b|
+-----------------------------+--------------+--------+
|2021-11-09T10:22:10.521+08:00| 1.0| 2.0|
|2021-11-09T10:22:17.231+08:00| 2.0| 3.0|
|2021-11-09T10:22:22.815+08:00| 3.0| 4.0|
|2021-11-17T10:21:58.790+08:00| 5.0| null|
+-----------------------------+--------------+--------+
SQL3:
select 'table1.root.sg.a' from (select a from root.sg) as 'table1'
结果集3:
+-----------------------------+----------------+
| Time|table1.root.sg.a|
+-----------------------------+----------------+
|2021-11-09T10:22:10.521+08:00| 1.0|
|2021-11-09T10:22:17.231+08:00| 2.0|
|2021-11-09T10:22:22.815+08:00| 3.0|
|2021-11-17T10:21:58.790+08:00| 5.0|
+-----------------------------+----------------+
在SQL2中,from
子句中同时出现了子查询和prefixPath
,prefixPath
也需要通过as
取别名。'table.b'中的b即为普通查询时使用的suffixPath
,相当于最后查询的是root.sg.b。
在SQL3中,子查询内部结果列没有取别名,那么在获取结果列时,columnName
就要使用子查询结果集原始列名,即root.sg.a。
时间序列生成函数查询(UDF查询)作为子查询
SQL1:
select 'table1.column1' from (select sin(a) as column1, sin(b) from root.sg) as 'table1'
结果集1:
+-----------------------------+-------------------+
| Time| table1.column1|
+-----------------------------+-------------------+
|2021-11-09T10:22:10.521+08:00| 0.8414709848078965|
|2021-11-09T10:22:17.231+08:00| 0.9092974268256817|
|2021-11-09T10:22:22.815+08:00| 0.1411200080598672|
|2021-11-17T10:21:58.790+08:00|-0.9589242746631385|
+-----------------------------+-------------------+
SQL2:
select 'table1.sin(root.sg.a)' from (select sin(a), sin(b) from root.sg) as 'table1'
结果集1:
+-----------------------------+--------------------------+
| Time| table1.sin(root.sg.a)|
+-----------------------------+--------------------------+
|2021-11-09T10:22:10.521+08:00| 0.8414709848078965|
|2021-11-09T10:22:17.231+08:00| 0.9092974268256817|
|2021-11-09T10:22:22.815+08:00| 0.1411200080598672|
|2021-11-17T10:21:58.790+08:00| -0.9589242746631385|
+-----------------------------+--------------------------+
嵌套表达式查询作为子查询
select 'table1.column1'
from (select ((a + 1) * 2 - 1) % 2 + 1.5 as column1 from root.sg) as 'table1'
Fill查询作为子查询
select 'table1.column1'
from (select a as column1 from root.sg where time = 10 fill(float [linear, 1ms, 1ms])) as 'table1'
Group By查询作为子查询
select 'table1.column1'
from (select avg(a) as column1 from root.sg group by ([1, 5), 1ms)) as 'table1
Group By Fill查询作为子查询
select 'table1.column1'
from (select avg(a) as column1 from root.sg1 group by ([1, 10),1ms) fill (float[PREVIOUS])) as 'table1