IoTDB 可实现的基本操作 : 数据导入、基本查询、聚合查询 | 小白教程文档(三)...

前言

上篇教程介绍了 Apache IoTDB 的基本架构、可部署形态、安装启动方法及数据模型,了解了这些 IoTDB 的基本概念,下面我们就将开始介绍 IoTDB 处理时序数据实现的具体功能和具体的操作命令。

本篇将介绍 Apache IoTDB 可实现的数据导入和查询相关的功能类型和 SQL 语句命令,后篇将介绍 IoTDB 如何实现数据的删除、导出和元数据操作。

1

导入时间序列

使用 Apache IoTDB,我们可以手动或者自动写入数据,还可以连接终端接收数据。此处先介绍自动导入已有的数据表格的方法。

1.1

IoTDB的架构

依然以上篇使用的实际工业应用场景为例,我们给出一个测试用的数据表格( CSV 格式),可点击 http://gofile.me/6WI2y/9TstJU5wt 下载,部分数据如下表所示。这是一段时序数据,记载了某集团的2号高山风机在某段时间内的轮毂温度。后续的 SQL 命令语句场景均以处理此表的时序数据为例。

1bda8de20ac18cfcf4afd1c01abec38c.png

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 构成的第一个存储组,完整的数据模式正如下图所示。

34f8e7cbd4189e6b35e3a11ffbb9d4c1.png

了解了导入数据的方法后,接下来我们将介绍 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 内置的聚合函数有:

13d5fbf8b1d91225ab68256c14e4ebf6.png

利用这些聚合函数,可以实现单层、分层聚合查询、分段聚合查询、空值填充等多种功能,下面就将详细介绍实现这些功能的过程。

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 子句中指定的聚合函数表达式返回查询结果。

这里我们重温一下测试数据和我们创建的数据的层级:

07e5280550349afde1a50800e5eadabb.png

根据上面的数据层级,如果我们查询 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 是时间窗口的滑动步长,如下图所示。

726def2e15725e9ab90a93faf1926192.png

下面我们看几个降采样查询的例子:

例句一:查询风机 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 可实现的其他功能,包括数据的删除、导出和元数据操作。

6dddfc76f4dc4feb178d2096d8cb9df8.gif

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenTSDB旨在在查询执行期间有效地组合多个不同的时间序列。这样做的原因是,当用户查看他们的数据时,他们通常会从较高的级别开始询问诸如“数据中心的总吞吐量是多少?”之类的问题。或“按地区划分的当前用功耗是多少?”。在查看这些高级别值之后,可能会出现一个或多个值,因此用户可以深入研究更详细的数据集,例如“我的LAX数据中心主机的吞吐量是多少?”。我们希望能够轻松回答这些高级问题,但仍然可以深入了解更多细节。 但是,如何将多个单独的时间序列合并为一个系列的数据呢?聚合函数提供了将不同时间序列数学方式将不同时间序列合并为一个的方法。过滤器用于按标签对结果进行分组,然后将聚合应用于每个组。聚合类似于SQL的GROUP BY子句,其中用户选择预定义的聚合函数以将多个记录合并为单个结果。但是在TSD中,每个时间戳和组聚合一组记录。 每个聚合器都有两个组件: 功能 - 应用的数学计算,例如对所有值求和,计算平均值或选择最高值。 插值 - 一种处理缺失值的方法,例如当时间序列A的值为T1但时间序列B没有值时。 本文档重点介绍如何在一个组中按上下文使用聚合器,即将多个时间序列合并为一个时。此外,聚合器可用于下采样时间序列(即返回较低分辨率的结果集)。有关更多信息,请参阅下采样。
在 Django 中,聚合查询是指对模型数据进行统计、分组、排序等操作查询。而 annotate() 是聚合查询中的一个常用方法,它可以在查询结果中添加一个聚合函数的值,并将该值作为一个新的属性添加到查询结果的每个对象中。 annotate() 方法的参数可以是一个聚合函数,也可以是一个表达式。聚合函数包括:Count、Avg、Sum、Max、Min 等,而表达式则是由模型中的字段和操作符组成的一个字符串。 以下是一些例子: ```python from django.db.models import Count from .models import Book, Author # 统计每个作者的书籍数量 authors = Author.objects.annotate(num_books=Count('book')) # 统计每个作者的平均书籍价格 authors = Author.objects.annotate(avg_price=Avg('book__price')) # 统计每个作者的最高书籍价格 authors = Author.objects.annotate(max_price=Max('book__price')) # 统计每个作者的书籍总价值 authors = Author.objects.annotate(total_price=Sum('book__price')) # 统计每个作者的书籍数量,并将结果按照数量从多到少排序 authors = Author.objects.annotate(num_books=Count('book')).order_by('-num_books') ``` 在上面的例子中,annotate() 方法的参数都是一个字符串,它们表示不同的聚合函数或表达式。其中,`'book'` 表示一个外键,它指向 Book 模型;`'book__price'` 表示一个跨表查询,它找到与 Book 关联的 Price 字段。 所以在使用 annotate() 的时候,需要根据具体的需求来设置参数,将其设置为合适的聚合函数或表达式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Apache IoTDB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值