子查询(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
  • No labels