IoTDB 可实现的基本操作 : 数据导入、基本查询、聚合查询 | 小白教程文档(三)...
前言上篇教程介绍了 Apache IoTDB 的基本架构、可部署形态、安装启动方法及数据模型,了解了这些 IoTDB 的基本概念,下面我们就将开始介绍 IoTDB 处理时序数据实现的具体功能和具体的操作命令。本篇将介绍 Apache IoTDB 可实现的数据导入和查询相关的功能类型和 SQL 语句命令,后篇将介绍 IoTDB 如何实现数据的删除、导出和元数据操作。1导入时间序列使用 Apache
前言
上篇教程介绍了 Apache IoTDB 的基本架构、可部署形态、安装启动方法及数据模型,了解了这些 IoTDB 的基本概念,下面我们就将开始介绍 IoTDB 处理时序数据实现的具体功能和具体的操作命令。
本篇将介绍 Apache IoTDB 可实现的数据导入和查询相关的功能类型和 SQL 语句命令,后篇将介绍 IoTDB 如何实现数据的删除、导出和元数据操作。
1
导入时间序列
使用 Apache IoTDB,我们可以手动或者自动写入数据,还可以连接终端接收数据。此处先介绍自动导入已有的数据表格的方法。
1.1
IoTDB的架构
依然以上篇使用的实际工业应用场景为例,我们给出一个测试用的数据表格( CSV 格式),可点击 http://gofile.me/6WI2y/9TstJU5wt 下载,部分数据如下表所示。这是一段时序数据,记载了某集团的2号高山风机在某段时间内的轮毂温度。后续的 SQL 命令语句场景均以处理此表的时序数据为例。
1.2
CSV 导入时间序列和值
接下来利用 Apache IoTDB 中 tools 文件夹下的 CSV 工具,可以将 CSV 格式的上表数据导入 IoTDB 中。
首先我们启动 IoTDB server,然后去到 tools 目录,输入指令。Linux 和 Mac 系统下的指令格式为:
import-csv.sh -h <ip> -p <port> -u <username> -pw <password> -f <xxx.csv> [-fd <./failedDirectory>]
其中 -f 指定了要导入的数据,如果指定的是文件夹,就会把文件夹中所有的后缀为 TXT 与 CSV 的文件进行批量导入。-fd 指定了一个目录来存放保存失败的文件,如果没有指定这个参数,失败的文件将会被保存到源数据的目录中,文件名为源文件名加上 .failed 的后缀。
假如我将“ TestData.csv ”这个测试数据文件下载到了 usr 文件夹,那么我的导入文件指令则为:
./import-csv.sh -h 127.0.0.1 -p 6667 -u root -pw root -f /usr/TestData.csv -fd ./failed
显示“ Import completely! ”则为导入成功。
1.3
SQL 写入序列和值
当前已导入了一张表格,即测试数据 TestData ,这在 Apache IoTDB 中仅为一个存储组中的一条时间序列。为后续学习更多查询操作,除测试数据的时间序列外,此处再创建一条简单的时间序列,并往里面写一个值。
1.3.1 创建单条时间序列
我们可以使用 create timeseries 语句来创建时间序列,SQL 语句为:
create timeseries root.BHSFC.Q1.W003.speed FLOAT encoding=RLE
创建时间序列需要指定数据类型和编码方式,这里指定了 FLOAT 和 RLE 。
1.3.2 写入数据
我们可以使用如下 SQL 语句在上条时间序列中写一个值:
insert into root.BHSFC.Q1.W003(timestamp,speed) values(1657468800000,1)
timestamp 是时间戳,我们把要写入的时间(此处设定为 2022 年 7 月 11 日 0 点 0 分 0 秒)转换为时间戳 1657468800000 输入,speed 的值写入1。
1.3.3 创建多条时间序列
我们也可以创建同一设备下的多条时间序列,这里我们按照数据模式往时间序列中插入值,就会自动创建对应的对齐时间序列,SQL 语句为:
insert into root.ln1.wf01(time, status, temperature) aligned values(1657468800000, 0, 1)
这样我们就得到了两条属于第二个存储组,共享 1657468800000 这个时间戳,值分别为 0 和 1 的时间序列root.ln.wf01.status 和root.ln.wf01.temperature ,加上测试数据 TestData 构成的第一个存储组,完整的数据模式正如下图所示。
了解了导入数据的方法后,接下来我们将介绍 Apache IoTDB 如何实现对时序数据的基本查询功能。基本查询功能可通过两类 SQL 语句实现:select from 语句查询和 where 语句查询。
2
数据基本查询
2.1
使用 select from 语句查询
2.1.1 查询单个时间序列的数据
查询导入的测试数据中的所有行数据,可使用如下 SQL 语句:
select WROT_HubTmp from root.BHSFC.Q1.W002
输出的结果如下(仅截取前 6 行数据):
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-11T21:51:40.000+08:00| 14.4|
|2022-01-11T21:51:54.000+08:00| 14.5|
|2022-01-11T21:52:01.000+08:00| 14.4|
|2022-01-11T21:53:56.000+08:00| 14.3|
|2022-01-11T21:54:14.000+08:00| 14.4|-
|2022-01-11T21:56:17.000+08:00| 14.3|
查询结果默认显示 1000 行,也可以限制显示的数目,在末尾加上“limit <数目>”即可。如只要显示 10 行,SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 limit 10
也可以限制起始行数,SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 limit 2 offset 2
这样查询的结果就会从第三行开始显示,且只显示两个数据:
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 limit 2 offset 2
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-11T05:52:01.000+08:00| 14.4|
|2022-01-11T05:53:56.000+08:00| 14.3|
+-----------------------------+------------------------------+
Total line number = 2
查询的结果默认按时间由远到近排列,如果我们想要最新的时间显示在前面,则加上 ORDER BY TIME DESC 子句。例如查询最新的五条数据,SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 order by time desc limit 5
输出的结果如下:
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 order by time desc limit 5
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-15T06:46:40.000+08:00| 16.0|
|2022-01-15T06:46:28.000+08:00| 15.9|
|2022-01-15T06:46:02.000+08:00| 16.0|
|2022-01-15T06:45:56.000+08:00| 15.9|
|2022-01-15T06:45:50.000+08:00| 16.0|
+-----------------------------+------------------------------+
Total line number = 5
而查询我们用 SQL 语句写入的 speed 时间序列,可使用如下 SQL 语句:
select speed from root.BHSFC.Q1.W003
输出的结果如下:
IoTDB> select speed from root.BHSFC.Q1.W003
+-----------------------------+------------------------+
| Time|root.BHSFC.Q1.W003.speed|
+-----------------------------+------------------------+
|2022-07-11T00:00:00.000+08:00| 1.0|
+-----------------------------+------------------------+
Total line number = 1
可以看到之前插入时输入的时间戳 1657468800000 自动转换成了时间:2022 年 7 月 11 日 0 点 0 分 0 秒。
2.1.2 查询多个时间序列的数据
如果要查询多个时间序列的数据,可以输入 SQL 语句:
select * from root.BHSFC.** limit 10
* 是通配符,可以代替字符,进行模糊查询。在路径中 * 表示一层,** 表示一层或多层。输入上述 SQL 语句,就会显示这两条时间序列root.BHSFC.Q1.W002.WROT_HubTmp和root.BHSFC.Q1.W003.speed 的前十个值,以上的查询结果默认按照时间戳大小升序排列,即日期从远到近。如果要使查询结果按日期从近到远排列,则可输入 SQL 语句:
select WROT_HubTmp from root.BHSFC.Q1.W002 order by time desc
2.1.3 查询最新数据
如果要查询指定时间序列的最新数据,可以输入 SQL 语句:
select last WROT_HubTmp from root.BHSFC.Q1.W002
查询结果为:
IoTDB> select last WROT_HubTmp from root.BHSFC.Q1.W002
+-----------------------------+------------------------------+-----+--------+
| Time| timeseries|value|dataType|
+-----------------------------+------------------------------+-----+--------+
|2022-01-15T06:46:40.000+08:00|root.BHSFC.Q1.W002.WROT_HubTmp| 16.0| DOUBLE|
+-----------------------------+------------------------------+-----+--------+
Total line number = 1
也可以查询多个时间序列的最新值,可使用如下 SQL 语句:
select last * from root.BHSFC.**
查询结果为:
ulimitIoTDB> select last * from root.BHSFC.**
+-----------------------------+------------------------------+-----+--------+
| Time| timeseries|value|dataType|
+-----------------------------+------------------------------+-----+--------+
|2022-01-15T06:46:40.000+08:00|root.BHSFC.Q1.W002.WROT_HubTmp| 16.0| DOUBLE|
|2022-07-11T00:00:00.000+08:00| root.BHSFC.Q1.W003.speed| 1.0| FLOAT|
+-----------------------------+------------------------------+-----+--------+
Total line number = 2 -Hn
2.2
使用 where 语句查询
2.2.1 时间过滤查询
我们可以查询某个时间段的数据,例如查询测试数据中 2022 年 1 月 12 日之前的数据,输入的 SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where time <2022-01-12
输出的结果如下(仅截取前 3 行数据):
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where time <2022-01-12
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-11T21:51:40.000+08:00| 14.4|
|2022-01-11T21:51:54.000+08:00| 14.5|
|2022-01-11T21:52:01.000+08:00| 14.4|
也可以查询某个时刻之前的数据,例如查询测试数据中 2022 年 1 月 22 日 5 点之前的数据,输入的 SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where time <2022-01-12T05:00:00
输出的结果如下(仅截取前 3 行数据):
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where time <2022-01-12T05:00:00
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-11T21:51:40.000+08:00| 14.4|
|2022-01-11T21:51:54.000+08:00| 14.5|
|2022-01-11T21:52:01.000+08:00| 14.4|
2.2.2 查询时间范围内的最新数据
我们可以查询时间序列的最新数据,如查询时间序列 root.BHSFC.Q1.W002.WROT_HubTmp 的最新数据,可使用如下 SQL 语句:
select last WROT_HubTmp from root.BHSFC.Q1.W002
查询结果为:
IoTDB> select last WROT_HubTmp from root.BHSFC.Q1.W002
+-----------------------------+------------------------------+-----+--------+
| Time| timeseries|value|dataType|
+-----------------------------+------------------------------+-----+--------+
|2022-01-15T06:46:40.000+08:00|root.BHSFC.Q1.W002.WROT_HubTmp| 16.0| DOUBLE|
+-----------------------------+------------------------------+-----+--------+
Total line number = 1
也可以查询某个时间前后的最新数据,如查询 2022 年 1 月 14 日零点之前的最新值,SQL 语句为:
select last WROT_HubTmp from root.BHSFC.Q1.W002 where time >= 2022-1-14T00:00:00
2.2.3 值过滤查询
我们也可以查询值满足某些条件的数据,例如查询测试数据中值大于 20 的数据,输入的 SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where WROT_HubTmp > 20
输出的结果如下(仅截取前 3 行数据):
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where WROT_HubTmp > 20
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-13T04:14:42.000+08:00| 20.1|
|2022-01-13T04:19:52.000+08:00| 20.1|
|2022-01-13T04:43:09.000+08:00| 20.1|
或查询测试数据中值区间为[21,24]的数据,SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where WROT_HubTmp >= 21 and WROT_HubTmp < 24
输出的结果如下(仅截取前 3 行数据):
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where WROT_HubTmp >= 21 and WROT_HubTmp < 24
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-12T15:03:50.000+08:00| 21.0|
|2022-01-12T15:39:21.000+08:00| 21.0|
|2022-01-12T15:39:36.000+08:00| 21.1|
以上阐述的数据基本查询功能,执行命令后将直接返回值结果。然而对于求和、求平均数等希望对原始数据采取简单二次计算、继而返回计算结果的需求,如果先查出数值再计算会比较麻烦。
Apache IoTDB 为此类需求提供了内置的聚合函数,使用聚合函数一次查询即可完成求和、求平均数等类型的计算,即使用聚合查询,可以很快得到结果。下面将介绍聚合查询可实现的功能类型和使用的 SQL 命令。
3
数据聚合查询
3.1
查询时间序列行数
3.1.1 查询单条时间序列行数
要查询导入的 CSV 测试数据一共有多少行,可输入 SQL 语句:
select count(WROT_HubTmp) from root.BHSFC.Q1.W002
输出结果如下:
IoTDB> select count(WROT_HubTmp) from root.BHSFC.Q1.W002
+-------------------------------------+
|count(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-------------------------------------+
| 13834|
+-------------------------------------+
Total line number = 1
我们可以使用通配符简化查询语句,它的功能等价于上面的查询导入行数语句(*在路径中表示一层,**表示一层或多层):
select count(*) from root.**.W002
我们同样可以使用通配符 * 查询写入的 SQL 语句一共有多少行,SQL 语句如下:
select count(*) from root.**.W003
输出结果如下:
IoTDB> select count(*) from root.**.W003
+-------------------------------+
|count(root.BHSFC.Q1.W003.speed)|
+-------------------------------+
| 1|
+-------------------------------+
Total line number = 1
3.1.2 查询多条时间序列行数
我们也可以一次查询多条时间序列,输入的 SQL 语句为(已使用通配符简化输入的字符):
select count(*) from root.**
输出结果为写入的两条时间序列的名称和行数:
IoTDB> select count(*) from root.**
+-------------------------------------+-------------------------------+
|count(root.BHSFC.Q1.W002.WROT_HubTmp)|count(root.BHSFC.Q1.W003.speed)|
+-------------------------------------+-------------------------------+
| 13834| 1|
+-------------------------------------+-------------------------------+
Total line number = 1
3.2
IoTDB 内置聚合函数功能
上面查询时间序列使用的 count 查询即是一个聚合函数,Apache IoTDB 内置的聚合函数有:
利用这些聚合函数,可以实现单层、分层聚合查询、分段聚合查询、空值填充等多种功能,下面就将详细介绍实现这些功能的过程。
3.2.1 单层聚合查询
例如我们要查询导入的测试数据中的最大值,输入的 SQL 语句为:
select MAX_VALUE(*) from root.BHSFC.Q1.W002
输出结果为:
IoTDB> select MAX_VALUE(*) from root.BHSFC.Q1.W002
+---------------------------------------+
|EXTREME(root.BHSFC.Q1.W002.WROT_HubTmp)|
+---------------------------------------+
| 22.39999|
+---------------------------------------+
Total line number = 1
如果需要求测试数据的平均值,输入的 SQL 语句为:
select AVG(*) from root.BHSFC.Q1.W002
输出结果为:
IoTDB> select AVG(*) from root.BHSFC.Q1.W002
+-----------------------------------+
|AVG(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------------+
| 17.683083226110213|
+-----------------------------------+
Total line number = 1
3.2.2 聚合查询+时间过滤
我们也可以对一段时间内的数据进行聚合查询,例如查询 1 月 13 日之后的数据总数:
select count(*) from root.BHSFC.Q1.W002 where time > 2022-01-13T00:00:00
或查询 1 月 12 日至 1 月 13 日之间的数据总数:
select count(*) from root.BHSFC.Q1.W002 where time <= 2022-01-13T00:00:00 and time > 2022-01-12T00:00:00
两次查询的输出结果为:
IoTDB> select count(*) from root.BHSFC.Q1.W002 where time > 2022-01-13T00:00:00
+-------------------------------------+
|count(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-------------------------------------+
| 9985|
+-------------------------------------+
Total line number = 1
It costs 0.007s
IoTDB> select count(*) from root.BHSFC.Q1.W002 where time <= 2022-01-13T00:00:00 and time > 2022-01-12T00:00:00
+-------------------------------------+
|count(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-------------------------------------+
| 3030|
+-------------------------------------+
Total line number = 1
It costs 0.007s
3.2.3 分层聚合查询
我们可以使用 GROUP BY LEVEL = INT 语句来对某一层级下的序列进行聚合查询。group by 子句可以将查询结果分组,并按照 group by 子句中指定的聚合函数表达式返回查询结果。
这里我们重温一下测试数据和我们创建的数据的层级:
根据上面的数据层级,如果我们查询 level 2 层级中的数据点个数,可以这样写 SQL 语句:
select count(*) from root.** group by level = 2
输出结果如下:
IoTDB> select count(*) from root.** group by level = 2
+--------------------+--------------------+
|count(root.*.Q1.*.*)|count(root.*.wf01.*)|
+--------------------+--------------------+
| 13835| 2|
+--------------------+--------------------+
Total line number = 1
分层聚合查询还可以用于对某一层级下同名的序列的查询。
例如我们现在有 root.BHSFC.Q1.W002.speed序列,假如还有多条名为 speed 的序列,如
root.ln2.wf01.speed、root.ln2.wf02.speed、root.ln2.wf03.speed等。
如果需要统计所有这些 speed 序列的数据点数,SQL 语句为:
select count(speed) from root.** group by level = 3
由于这里没有实际创建上面这些序列,这里就不详细演示输出结果了,但这个操作非常方便,一句简单的 SQL 语句就能查询不同设备采集的同一物理量。
3.3
分段聚合查询
分段聚合是一种时序数据典型的查询方式,当我们按照一定的时间间隔进行聚合计算,比如计算每天的平均气温,就可以将气温的序列按天进行分段,然后计算每段的平均值。
我们通过 GROUP BY 子句指定按照时间区间分段聚合。例如查询测试数据中 1 月 14 号的平均风速,SQL 语句为:
select AVG(*) from root.BHSFC.Q1.W002 group by ([2022-1-14T00:00:00,2022-1-15T00:00:00),1d)
括号左开右闭代表计算时包含 1 月 14 号零点的数据,不包含 1 月 15 号零点的数据。输出结果如下:
IoTDB> select AVG(*) from root.BHSFC.Q1.W002 group by ([2022-1-14T00:00:00,2022-1-15T00:00:00),1d)
+-----------------------------+-----------------------------------+
| Time|AVG(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-----------------------------------+
|2022-01-14T00:00:00.000+08:00| 17.880594558648433|
+-----------------------------+-----------------------------------+
Total line number = 1
不仅单个时间序列可以进行时间区间分段聚合查询,多元时间序列也可以。例如我们可以查询 1 月 11 号到 1 月 15 号间每天前三小时内风速 speed 的数量和风速的最大值,SQL 语句如下:
select count(speed),max_value(WROT_HubTmp) from root.BHSFC.Q1.* group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),3h,1d)
输出结果为:
IoTDB> select count(speed),max_value(WROT_HubTmp) from root.BHSFC.Q1.* group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),3h,1d)
+-----------------------------+-------------------------------+-----------------------------------------+
| Time|count(root.BHSFC.Q1.W003.speed)|max_value(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-------------------------------+-----------------------------------------+
|2022-01-11T00:00:00.000+08:00| 0| null|
|2022-01-12T00:00:00.000+08:00| 0| 18.2|
|2022-01-13T00:00:00.000+08:00| 0| 18.8|
|2022-01-14T00:00:00.000+08:00| 0| 18.39999|
+-----------------------------+-------------------------------+-----------------------------------------+
Total line number = 4
因为我们此前只往 speed 写入了一个值,而这个值涉及的时间范围不包含在 1 月 11 日到 14 日内,所以这段时间内 speed 都没有值,统计的数据点数为 0 。而 1 月 11 日 0 点到 3 点的时间区间内,风速也没有值,所以下方这一栏显示为 null 。
max_value(root.BHSFC.Q1.W002.WROT_HubTmp)
除上述典型的分段聚合查询场景外,分段聚合查询还有功能上的特例,这就是下面要说的降采样查询。
3.3.1 降采样查询
降采样查询是指使用比数据采集的时间频率更低的频率进行的一种查询方式,是分段聚合的一种特例。例如,数据采集的频率是一秒,如果想按照 1 分钟的频率对数据进行查询,则需要使用降采样查询。
在 Apache IoTDB 中可以通过 GROUP BY 子句指定聚合的时间间隔和滑动步长实现降采样查询,样式为
group by([startTime, endTime], time_window, sliding_step)
其中 time_window 是聚合的时间窗口大小,sliding_step 是时间窗口的滑动步长,如下图所示。
下面我们看几个降采样查询的例子:
例句一:查询风机 2022 年 1 月 11 号到 15 号每天的最高风速:
select max_value (*) from root.BHSFC.Q1.W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),1d)
例句二:查询风机 2022 年 1 月 11 号到 15 号每天上午的平均风速:
select avg(*) from root.BHSFC.Q1.W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),12h,1d)
例句三:每隔半天统计 1 月 11 号之后 0 点到 6 点的平均风速:
select avg(*) from root.BHSFC.Q1. W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),6h,12h)
上述例句的输出结果如下:
IoTDB> select max_value (*) from root.BHSFC.Q1.W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),1d)
+-----------------------------+-----------------------------------------+
| Time|max_value(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-----------------------------------------+
|2022-01-11T00:00:00.000+08:00| 18.7|
|2022-01-12T00:00:00.000+08:00| 21.1|
|2022-01-13T00:00:00.000+08:00| 20.2|
|2022-01-14T00:00:00.000+08:00| 22.39999|
+-----------------------------+-----------------------------------------+
Total line number = 4
It costs 0.014s
IoTDB> select avg(*) from root.BHSFC.Q1.W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),12h,1d)
+-----------------------------+-----------------------------------+
| Time|avg(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-----------------------------------+
|2022-01-11T00:00:00.000+08:00| 14.475876229508224|
|2022-01-12T00:00:00.000+08:00| 16.913640732526957|
|2022-01-13T00:00:00.000+08:00| 17.04472683120057|
|2022-01-14T00:00:00.000+08:00| 16.626656189856803|
+-----------------------------+-----------------------------------+
Total line number = 4
It costs 0.010s
IoTDB> select avg(*) from root.BHSFC.Q1. W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),6h,12h)
+-----------------------------+-----------------------------------+
| Time|avg(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-----------------------------------+
|2022-01-11T00:00:00.000+08:00| 14.263634545454543|
|2022-01-11T12:00:00.000+08:00| null|
|2022-01-12T00:00:00.000+08:00| 16.590661805896843|
|2022-01-12T12:00:00.000+08:00| 19.916664648437486|
|2022-01-13T00:00:00.000+08:00| 16.908698723897892|
|2022-01-13T12:00:00.000+08:00| 18.385164558333372|
|2022-01-14T00:00:00.000+08:00| 16.478693331408735|
|2022-01-14T12:00:00.000+08:00| 20.17386738693474|
+-----------------------------+-----------------------------------+
Total line number = 8
3.3.2 分层+分段聚合查询
前面分层聚合中我们提到了对同名序列的查询,在分段聚合中我们也可以查询所有同名的序列。
例如如果不同存储组、不同设备的序列都命名为WROT_HubTmp如:root.BHSFC.Q2.W003.WROT_HubTmp、 root.ln2.wf01.WROT_HubTmp 等。
那么统计 2022 年 1 月 11 日至 15 日内所有设备下名叫 WROT_HubTmp 的序列每天的数据最大值,其 SQL 语句为:
select max_value(WROT_HubTmp) from root.** group by ((2022-1-11T00:00:00,2022-1-15T00:00:00],1d), level=3
3.4
空值填充
在数据传输过程中,很容易产生空值,Apache IoTDB 的查询提供了前值、线性和特定值填充三种方法来方便快捷的填补空值。
3.4.1 前值填充
IoTDB 中可以使用前一个数据的值来填充此条数据的空值。
以测试数据为例,测试数据中此前在最新值查询中查到了最后一个数据的时间为 2022 年 1 月 15 日 06:46:40,这之后的数据就没有了。假如需要查询在这之后,如 2022 年 1 月 16 日 00:00:00 的数据,并使用前一个数据的值填充空值,则 SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-16T00:00:00 fill(previous)
返回结果为:
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-15T23:00:00 fill(previous)
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-15T23:00:00.000+08:00| 16.0|
+-----------------------------+------------------------------+
Total line number = 1
可以看到这个时间点的值与前一个时间点的值相同。
我们也可以指定前值的时间范围,例如最后一个数据的时间为 2022 年 1 月 15 日 06:46:40,我们想要查询 2022 年 1 月 15 日 06:47:00 的数据,且想要填充数值位于空值前一分钟内,则 SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-15T06:47:00 fill(previous,1m)
返回结果为:
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-15T06:47:00 fill(previous,1m)
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-15T06:47:00.000+08:00| 16.0|
+-----------------------------+------------------------------+
Total line number = 1
如果不指定,则默认时间范围为无穷大,至找到前值为止。如果前一个时间点为空,那么填充指令返回的结果也为空。
例如我们的前值范围限定在 48 分的前一分钟,那个时间点没有数值,则返回 null ,如下所示:
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-15T06:48:00 fill(previous,1m)
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-15T06:48:00.000+08:00| null|
+-----------------------------+------------------------------+
Total line number = 1
3.4.2 线性填充
在降采样查询中我们有这样一个例句,每隔半天统计 1 月 11 号至 1 月 15 日 0 点到 6 点的平均风速:
select avg(*) from root.BHSFC.Q1. W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),6h,12h)
返回结果为:
IoTDB> select avg(*) from root.BHSFC.Q1. W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),6h,12h)
+-----------------------------+-----------------------------------+
| Time|avg(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-----------------------------------+
|2022-01-11T00:00:00.000+08:00| 14.263634545454543|
|2022-01-11T12:00:00.000+08:00| null|
|2022-01-12T00:00:00.000+08:00| 16.590661805896843|
|2022-01-12T12:00:00.000+08:00| 19.916664648437486|
|2022-01-13T00:00:00.000+08:00| 16.908698723897892|
|2022-01-13T12:00:00.000+08:00| 18.385164558333372|
|2022-01-14T00:00:00.000+08:00| 16.478693331408735|
|2022-01-14T12:00:00.000+08:00| 20.17386738693474|
+-----------------------------+-----------------------------------+
可以看到第二行数据返回了 null ,是空值,因为那段时间内没有数据。我们可以用线性填充把这个值填上,SQL 语句为:
select avg(*) from root.BHSFC.Q1. W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),6h,12h) fill (linear)
返回结果为:
IoTDB> select avg(*) from root.BHSFC.Q1. W002 group by ([2022-1-11T00:00:00,2022-1-15T00:00:00),6h,12h) fill (linear)
+-----------------------------+-----------------------------------+
| Time|avg(root.BHSFC.Q1.W002.WROT_HubTmp)|
+-----------------------------+-----------------------------------+
|2022-01-11T00:00:00.000+08:00| 14.263634545454543|
|2022-01-11T12:00:00.000+08:00| 15.427148175675693|
|2022-01-12T00:00:00.000+08:00| 16.590661805896843|
|2022-01-12T12:00:00.000+08:00| 19.916664648437486|
|2022-01-13T00:00:00.000+08:00| 16.908698723897892|
|2022-01-13T12:00:00.000+08:00| 18.385164558333372|
|2022-01-14T00:00:00.000+08:00| 16.478693331408735|
|2022-01-14T12:00:00.000+08:00| 20.17386738693474|
+-----------------------------+-----------------------------------+
可以看到空值已经被填充了,这个值是前值14.263634545454543 和后值 16.590661805896843 的线性插值。
3.4.3 特定值填充
我们也可以用特定的常值进行填充,例如 16 号零点的数据都为空,希望显示为 15 ,则 SQL 语句为:
select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-16T00:00:00 fill(15)
返回结果为:
IoTDB> select WROT_HubTmp from root.BHSFC.Q1.W002 where time = 2022-01-16T00:00:00 fill(15)
+-----------------------------+------------------------------+
| Time|root.BHSFC.Q1.W002.WROT_HubTmp|
+-----------------------------+------------------------------+
|2022-01-16T00:00:00.000+08:00| 15.0|
+-----------------------------+------------------------------+
4
结语
至此我们了解了 Apache IoTDB 可实现的数据导入和查询功能,和具体如何实现这些功能的 SQL 例句。接下来的最后一篇教程将介绍 IoTDB 可实现的其他功能,包括数据的删除、导出和元数据操作。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)