结果集空值过滤

在实际应用中,用户可能希望对查询的结果集中某些存在空值的行进行过滤。在 IoTDB 中,可以使用 WITHOUT NULL 子句对结果集中的空值进行过滤,有两种过滤策略:WITHOUT NULL ANYWITHOUT NULL ALL。不仅如此, WITHOUT NULL 子句支持指定相应列进行过滤。

WITHOUT NULL ANY: 指定的列集中,存在一列为NULL,则满足条件进行过滤

WITHOUT NULL ALL: 指定的列集中,所有列都为NULL,才满足条件进行过滤

不指定列

默认就是对结果集中的所有列生效,即指定的列集为结果集中的所有列

  1. 在下列查询中,如果结果集中某一行任意一列为 null,则过滤掉该行;即获得的结果集不包含任何空值。
  1. select * from root.ln.** where time <= 2017-11-01T00:01:00 WITHOUT NULL ANY
  1. 在下列查询中,如果结果集的某一行所有列都为 null,则过滤掉该行;即获得的结果集不包含所有值都为 null 的行。
  1. select * from root.ln.** where group by ([1,10), 2ms) WITHOUT NULL ALL

指定列

只对指定的列集生效

使用 WITHOUT NULL子句对结果集中指定列名的空值进行过滤,下面是一些例子及其说明:

注意,如果指定的列在当前元数据里不存在则会直接过滤掉,这与目前查询列的输出结果是一致的; 如果指定的列存在,但与结果集中输出的列名不匹配,则会报错: The without null columns don't match the columns queried.If has alias, please use the alias.

比如下面的例子

  1. 比如without null指定的列集中root.test.sg1.s1列在元数据中存在,root.test.sg1.usag列在元数据不存在,则下面查询的without null子句的作用相当于without null all(s1)
  1. select * from root.test.sg1 without null all (s1, usag)
  1. 比如without null指定的列集中root.test.sg1.s2列在元数据中存在,但查询的结果集中输出列不包括,所以会报错:The without null columns don't match the columns queried.If has alias, please use the alias.
  1. select s1 + s2, s1 - s2, s1 * s2, s1 / s2, s1 % s2 from root.test.sg1 without null all (s1+s2, s2)

原始数据查询

  1. 如果查询的结果集中, root.ln.sg1.s1这一列如果为null,则过滤掉该行
  1. select * from root.ln.sg1 WITHOUT NULL ANY(s1)
  1. 如果查询的结果集中, root.ln.sg1.s1和root.ln.sg1.s2中只要存在至少一列为null,则过滤掉该行
  1. select * from root.ln.sg1 WITHOUT NULL ANY(s1, s2)
  1. 如果查询的结果集中, 只要root.ln.sg1.s1和root.ln.sg1.s2这两列都为null,则过滤掉该行
  1. select * from root.ln.sg1 WITHOUT NULL ALL(s1, s2)

带表达式查询

指定的列可以为表达式

  1. 计算s2+s4和s2这两列是否都为null,如果是则过滤
  1. select s2, - s2, s4, + s4, s2 + s4, s2 - s4, s2 * s4, s2 / s4, s2 % s4 from root.test.sg1 without null all (s2+s4, s2)
  1. 计算s2+s4和s2这两列是否至少有一列为null,如果是则过滤
  1. select s2, - s2, s4, + s4, s2 + s4, s2 - s4, s2 * s4, s2 / s4, s2 % s4 from root.test.sg1 without null any (s2+s4, s2)

别名

指定的列可以为别名

  1. 计算t2和t1这两列是否都为null,如果是则过滤
  1. select s2 as t1, - s2, s4, + s4, s2 + s4 as t2, s2 - s4, s2 * s4, s2 / s4, s2 % s4 from root.test.sg1 without null all (t2, t1)
  1. select s1, sin(s2) + cos(s2) as t1, cos(sin(s2 + s4) + s2) as t2 from root.test.sg1 without null all (t1, t2)
  1. 当你指定了别名,如果在without null指定的列集中再使用原始列名,则会报错:The without null columns don't match the columns queried.If has alias, please use the alias. 比如下面同时使用了tan(s1)和t
  1. select s1 as d, sin(s1), cos(s1), tan(s1) as t, s2 from root.test.sg1 without null all(d, tan(s1), t) limit 5

带函数查询

  1. select s1, sin(s2) + cos(s2), cos(sin(s2 + s4) + s2) from root.test.sg1 without null all (sin(s2) + cos(s2), cos(sin(s2 + s4) + s2))

按设备对齐查询

  1. select last_value(*) from root.test.sg1 group by([1,10), 2ms) without null all(last_value(s2), last_value(s3)) align by device

结果示例如下:

  1. IoTDB> select last_value(*) from root.sg1.* group by([1,10), 2ms) without null all(last_value(s2), last_value(s3)) align by device
  2. +-----------------------------+-----------+--------------+--------------+--------------+
  3. | Time| Device|last_value(s1)|last_value(s2)|last_value(s3)|
  4. +-----------------------------+-----------+--------------+--------------+--------------+
  5. |1970-01-01T08:00:00.001+08:00|root.sg1.d1| 1.0| 2.0| null|
  6. |1970-01-01T08:00:00.003+08:00|root.sg1.d1| 3.0| 4.0| null|
  7. |1970-01-01T08:00:00.001+08:00|root.sg1.d2| 1.0| 1.0| 1.0|
  8. +-----------------------------+-----------+--------------+--------------+--------------+
  9. Total line number = 3
  10. It costs 0.007s

指定的列名是与输出结果的列名对应,目前without null子句不支持指定某设备的某列,会报错:The without null columns don't match the columns queried.If has alias, please use the alias. 比如下面这个查询例子,指定last_value(root.sg1.d1.s3)为null的行进行过滤,目前是不支持的。

  1. select last_value(*) from root.test.sg1 group by([1,10), 2ms) without null all(last_value(`root.sg1.d1.s3`)) align by device

聚合查询

  1. select avg(s4), sum(s2) from root.test.sg1 group by ([1,10), 2ms) without null all(sum(s2))
  1. select avg(s4), sum(s2), count(s3) from root.test.sg1 group by ([1,10), 2ms) without null all(avg(s4), sum(s2))

指定全路径列名

假设下面的查询输出的结果列为”root.test.sg1.s2”, “root.test.sg1.s3”, “root.test.sg2.s2”, “root.test.sg2.s3”四个,可以使用全路径名指定相应列进行过滤,比如下面的例子:

  1. 指定root.test.sg1.s2, root.test.sg2.s3两列都为null则过滤
  1. select s2, s3 from root.test.** without null all(`root.test.sg1.s2`, `root.test.sg2.s3`)
  1. 指定root.test.sg1.s2, root.test.sg1.s3, root.test.sg2.s3三列都为null则过滤
  1. select s2, s3 from root.test.** without null all(`root.test.sg1.s2`, s3)

对齐序列查询

  1. 可以指定without null 子句后的列名为对齐序列列名
  1. CREATE ALIGNED TIMESERIES root.test.sg3(s5 INT32, s6 BOOLEAN, s7 DOUBLE, s8 INT32)
  2. select sg1.s1, sg1.s2, sg2.s3, sg3.* from root.test without null all (sg3.s5, sg3.s6, sg2.s3)