Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

<!--

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.

-->

子查询(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子句

  • 结果集数据类型为数值类型,即不是BooleanText类型

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子句中同时出现了子查询和prefixPathprefixPath也需要通过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