数据查询
概述
在 IoTDB 中,使用 SELECT 语句从一条或多条时间序列中查询数据,IoTDB 不区分历史数据和实时数据,用户可以用统一的sql语法进行查询,通过 WHERE 子句中的时间过滤谓词决定查询的时间范围。
语法定义
1. SELECT [LAST] selectExpr [, selectExpr] ...
2. [INTO intoItem [, intoItem] ...]
3. FROM prefixPath [, prefixPath] ...
4. [WHERE whereCondition]
5. [GROUP BY {
6. ([startTime, endTime), interval [, slidingStep]) |
7. LEVEL = levelNum [, levelNum] ... |
8. TAGS(tagKey [, tagKey] ... |
9. VARIATION(expression[,delta][,ignoreNull=true/false]) |
10. CONDITION(expression,[keep>/>=/=/</<=]threshold[,ignoreNull=true/false]) |
11. SESSION(timeInterval) |
12. COUNT(expression, size[,ignoreNull=true/false])
13. }]
14. [HAVING havingCondition]
15. [ORDER BY sortKey {ASC | DESC}]
16. [FILL ({PREVIOUS | LINEAR | constant})]
17. [SLIMIT seriesLimit] [SOFFSET seriesOffset]
18. [LIMIT rowLimit] [OFFSET rowOffset]
19. [ALIGN BY {TIME | DEVICE}]
语法说明
SELECT 子句
SELECT子句指定查询的输出,由若干个selectExpr组成。- 每个
selectExpr定义查询结果中的一列或多列,它是一个由时间序列路径后缀、常量、函数和运算符组成的表达式。 - 支持使用
AS为查询结果集中的列指定别名。 - 在
SELECT子句中使用LAST关键词可以指定查询为最新点查询
INTO 子句
SELECT INTO用于将查询结果写入一系列指定的时间序列中。INTO子句指定了查询结果写入的目标时间序列。
FROM 子句
FROM子句包含要查询的一个或多个时间序列的路径前缀,支持使用通配符。- 在执行查询时,会将
FROM子句中的路径前缀和SELECT子句中的后缀进行拼接得到完整的查询目标序列。
WHERE 子句
WHERE子句指定了对数据行的筛选条件,由一个whereCondition组成。whereCondition是一个逻辑表达式,对于要选择的每一行,其计算结果为真。如果没有WHERE子句,将选择所有行。- 在
whereCondition中,可以使用除聚合函数之外的任何 IOTDB 支持的函数和运算符。
GROUP BY 子句
GROUP BY子句指定对序列进行分段或分组聚合的方式。- 分段聚合是指按照时间维度,针对同时间序列中不同数据点之间的时间关系,对数据在行的方向进行分段,每个段得到一个聚合值。目前支持时间区间分段、差值分段、条件分段、会话分段和点数分段,未来将支持更多分段方式。
- 分组聚合是指针对不同时间序列,在时间序列的潜在业务属性上分组,每个组包含若干条时间序列,每个组得到一个聚合值。支持按路径层级分组和按序列标签分组两种分组方式。
- 分段聚合和分组聚合可以混合使用。
HAVING 子句
HAVING子句指定了对聚合结果的筛选条件,由一个havingCondition组成。havingCondition是一个逻辑表达式,对于要选择的聚合结果,其计算结果为真。如果没有HAVING子句,将选择所有聚合结果。HAVING要和聚合函数以及GROUP BY子句一起使用。
ORDER BY 子句
ORDER BY子句用于指定结果集的排序方式。- 按时间对齐模式下:默认按照时间戳大小升序排列,可以通过
ORDER BY TIME DESC指定结果集按照时间戳大小降序排列。 - 按设备对齐模式下:默认按照设备名的字典序升序排列,每个设备内部按照时间戳大小升序排列,可以通过
ORDER BY子句调整设备列和时间列的排序优先级。
FILL 子句
FILL子句用于指定数据缺失情况下的填充模式,允许用户按照特定的方法对任何查询的结果集填充空值。
SLIMIT 和 SOFFSET 子句
SLIMIT指定查询结果的列数,SOFFSET指定查询结果显示的起始列位置。SLIMIT和SOFFSET仅用于控制值列,对时间列和设备列无效。
LIMIT 和 OFFSET 子句
LIMIT指定查询结果的行数,OFFSET指定查询结果显示的起始行位置。
ALIGN BY 子句
- 查询结果集默认按时间对齐,包含一列时间列和若干个值列,每一行数据各列的时间戳相同。
- 除按时间对齐之外,还支持按设备对齐,查询结果集包含一列时间列、一列设备列和若干个值列。
SQL 示例
IoTDB 支持即席(Ad_hoc)查询,即支持用户在使用系统时,自定义查询条件,根据自己当时的需求写出查询sql并执行。用户可以通过上述介绍的子句,进行组合,指定任意合法的过滤条件来满足当时的查询需求,下面介绍了一些查询的示例:
示例1:根据一个时间区间选择一列数据
SQL 语句为:
1. select temperature from root.ln.wf01.wt01 where time < 2017-11-01T00:08:00.000
其含义为:
被选择的设备为 ln 集团 wf01 子站 wt01 设备;被选择的时间序列为温度传感器(temperature);该语句要求选择出该设备在 “2017-11-01T00:08:00.000” 时间点以前的所有温度传感器的值。
该 SQL 语句的执行结果如下:
1. +-----------------------------+-----------------------------+
2. | Time|root.ln.wf01.wt01.temperature|
3. +-----------------------------+-----------------------------+
4. |2017-11-01T00:00:00.000+08:00| 25.96|
5. |2017-11-01T00:01:00.000+08:00| 24.36|
6. |2017-11-01T00:02:00.000+08:00| 20.09|
7. |2017-11-01T00:03:00.000+08:00| 20.18|
8. |2017-11-01T00:04:00.000+08:00| 21.13|
9. |2017-11-01T00:05:00.000+08:00| 22.72|
10. |2017-11-01T00:06:00.000+08:00| 20.71|
11. |2017-11-01T00:07:00.000+08:00| 21.45|
12. +-----------------------------+-----------------------------+
13. Total line number = 8
14. It costs 0.026s
示例2:根据一个时间区间选择多列数据
SQL 语句为:
1. select status, temperature from root.ln.wf01.wt01 where time > 2017-11-01T00:05:00.000 and time < 2017-11-01T00:12:00.000;
其含义为:
被选择的设备为 ln 集团 wf01 子站 wt01 设备;被选择的时间序列为供电状态(status)和温度传感器(temperature);该语句要求选择出 “2017-11-01T00:05:00.000” 至 “2017-11-01T00:12:00.000” 之间的所选时间序列的值。
该 SQL 语句的执行结果如下:
1. +-----------------------------+------------------------+-----------------------------+
2. | Time|root.ln.wf01.wt01.status|root.ln.wf01.wt01.temperature|
3. +-----------------------------+------------------------+-----------------------------+
4. |2017-11-01T00:06:00.000+08:00| false| 20.71|
5. |2017-11-01T00:07:00.000+08:00| false| 21.45|
6. |2017-11-01T00:08:00.000+08:00| false| 22.58|
7. |2017-11-01T00:09:00.000+08:00| false| 20.98|
8. |2017-11-01T00:10:00.000+08:00| true| 25.52|
9. |2017-11-01T00:11:00.000+08:00| false| 22.91|
10. +-----------------------------+------------------------+-----------------------------+
11. Total line number = 6
12. It costs 0.018s
示例3:按照多个时间区间选择同一设备的多列数据
IoTDB 支持在一次查询中指定多个时间区间条件,用户可以根据需求随意组合时间区间条件。例如,
SQL 语句为:
1. select status, temperature from root.ln.wf01.wt01 where (time > 2017-11-01T00:05:00.000 and time < 2017-11-01T00:12:00.000) or (time >= 2017-11-01T16:35:00.000 and time <= 2017-11-01T16:37:00.000);
其含义为:
被选择的设备为 ln 集团 wf01 子站 wt01 设备;被选择的时间序列为“供电状态(status)”和“温度传感器(temperature)”;该语句指定了两个不同的时间区间,分别为“2017-11-01T00:05:00.000 至 2017-11-01T00:12:00.000”和“2017-11-01T16:35:00.000 至 2017-11-01T16:37:00.000”;该语句要求选择出满足任一时间区间的被选时间序列的值。
该 SQL 语句的执行结果如下:
1. +-----------------------------+------------------------+-----------------------------+
2. | Time|root.ln.wf01.wt01.status|root.ln.wf01.wt01.temperature|
3. +-----------------------------+------------------------+-----------------------------+
4. |2017-11-01T00:06:00.000+08:00| false| 20.71|
5. |2017-11-01T00:07:00.000+08:00| false| 21.45|
6. |2017-11-01T00:08:00.000+08:00| false| 22.58|
7. |2017-11-01T00:09:00.000+08:00| false| 20.98|
8. |2017-11-01T00:10:00.000+08:00| true| 25.52|
9. |2017-11-01T00:11:00.000+08:00| false| 22.91|
10. |2017-11-01T16:35:00.000+08:00| true| 23.44|
11. |2017-11-01T16:36:00.000+08:00| false| 21.98|
12. |2017-11-01T16:37:00.000+08:00| false| 21.93|
13. +-----------------------------+------------------------+-----------------------------+
14. Total line number = 9
15. It costs 0.018s
示例4:按照多个时间区间选择不同设备的多列数据
该系统支持在一次查询中选择任意列的数据,也就是说,被选择的列可以来源于不同的设备。例如,SQL 语句为:
1. select wf01.wt01.status, wf02.wt02.hardware from root.ln where (time > 2017-11-01T00:05:00.000 and time < 2017-11-01T00:12:00.000) or (time >= 2017-11-01T16:35:00.000 and time <= 2017-11-01T16:37:00.000);
其含义为:
被选择的时间序列为 “ln 集团 wf01 子站 wt01 设备的供电状态” 以及 “ln 集团 wf02 子站 wt02 设备的硬件版本”;该语句指定了两个时间区间,分别为 “2017-11-01T00:05:00.000 至 2017-11-01T00:12:00.000” 和 “2017-11-01T16:35:00.000 至 2017-11-01T16:37:00.000”;该语句要求选择出满足任意时间区间的被选时间序列的值。
该 SQL 语句的执行结果如下:
1. +-----------------------------+------------------------+--------------------------+
2. | Time|root.ln.wf01.wt01.status|root.ln.wf02.wt02.hardware|
3. +-----------------------------+------------------------+--------------------------+
4. |2017-11-01T00:06:00.000+08:00| false| v1|
5. |2017-11-01T00:07:00.000+08:00| false| v1|
6. |2017-11-01T00:08:00.000+08:00| false| v1|
7. |2017-11-01T00:09:00.000+08:00| false| v1|
8. |2017-11-01T00:10:00.000+08:00| true| v2|
9. |2017-11-01T00:11:00.000+08:00| false| v1|
10. |2017-11-01T16:35:00.000+08:00| true| v2|
11. |2017-11-01T16:36:00.000+08:00| false| v1|
12. |2017-11-01T16:37:00.000+08:00| false| v1|
13. +-----------------------------+------------------------+--------------------------+
14. Total line number = 9
15. It costs 0.014s
示例5:根据时间降序返回结果集
IoTDB 支持 order by time 语句,用于对结果按照时间进行降序展示。例如,SQL 语句为:
1. select * from root.ln.** where time > 1 order by time desc limit 10;
语句执行的结果为:
1. +-----------------------------+--------------------------+------------------------+-----------------------------+------------------------+
2. | Time|root.ln.wf02.wt02.hardware|root.ln.wf02.wt02.status|root.ln.wf01.wt01.temperature|root.ln.wf01.wt01.status|
3. +-----------------------------+--------------------------+------------------------+-----------------------------+------------------------+
4. |2017-11-07T23:59:00.000+08:00| v1| false| 21.07| false|
5. |2017-11-07T23:58:00.000+08:00| v1| false| 22.93| false|
6. |2017-11-07T23:57:00.000+08:00| v2| true| 24.39| true|
7. |2017-11-07T23:56:00.000+08:00| v2| true| 24.44| true|
8. |2017-11-07T23:55:00.000+08:00| v2| true| 25.9| true|
9. |2017-11-07T23:54:00.000+08:00| v1| false| 22.52| false|
10. |2017-11-07T23:53:00.000+08:00| v2| true| 24.58| true|
11. |2017-11-07T23:52:00.000+08:00| v1| false| 20.18| false|
12. |2017-11-07T23:51:00.000+08:00| v1| false| 22.24| false|
13. |2017-11-07T23:50:00.000+08:00| v2| true| 23.7| true|
14. +-----------------------------+--------------------------+------------------------+-----------------------------+------------------------+
15. Total line number = 10
16. It costs 0.016s
查询执行接口
在 IoTDB 中,提供两种方式执行数据查询操作:
- 使用 IoTDB-SQL 执行查询。
- 常用查询的高效执行接口,包括时间序列原始数据范围查询、最新点查询、简单聚合查询。
使用 IoTDB-SQL 执行查询
数据查询语句支持在 SQL 命令行终端、JDBC、JAVA / C++ / Python / Go 等编程语言 API、RESTful API 中使用。
- 在 SQL 命令行终端中执行查询语句:启动 SQL 命令行终端,直接输入查询语句执行即可,详见 SQL 命令行终端。
- 在 JDBC 中执行查询语句,详见 JDBC 。
- 在 JAVA / C++ / Python / Go 等编程语言 API 中执行查询语句,详见应用编程接口一章相应文档。接口原型如下:
1. SessionDataSet executeQueryStatement(String sql);
- 在 RESTful API 中使用,详见 HTTP API V1 或者 HTTP API V2。
常用查询的高效执行接口
各编程语言的 API 为常用的查询提供了高效执行接口,可以省去 SQL 解析等操作的耗时。包括:
- 时间序列原始数据范围查询:
- 指定的查询时间范围为左闭右开区间,包含开始时间但不包含结束时间。
1. SessionDataSet executeRawDataQuery(List<String> paths, long startTime, long endTime);
- 最新点查询:
- 查询最后一条时间戳大于等于某个时间点的数据。
1. SessionDataSet executeLastDataQuery(List<String> paths, long lastTime);
- 聚合查询:
- 支持指定查询时间范围。指定的查询时间范围为左闭右开区间,包含开始时间但不包含结束时间。
- 支持按照时间区间分段查询。
1. SessionDataSet executeAggregationQuery(List<String> paths, List<Aggregation> aggregations);
3. SessionDataSet executeAggregationQuery(
4. List<String> paths, List<Aggregation> aggregations, long startTime, long endTime);
6. SessionDataSet executeAggregationQuery(
7. List<String> paths,
8. List<Aggregation> aggregations,
9. long startTime,
10. long endTime,
11. long interval);
13. SessionDataSet executeAggregationQuery(
14. List<String> paths,
15. List<Aggregation> aggregations,
16. long startTime,
17. long endTime,
18. long interval,
19. long slidingStep);
选择表达式(SELECT FROM 子句)
SELECT 子句指定查询的输出,由若干个 selectExpr 组成。 每个 selectExpr 定义了查询结果中的一列或多列。
selectExpr 是一个由时间序列路径后缀、常量、函数和运算符组成的表达式。即 selectExpr 中可以包含:
- 时间序列路径后缀(支持使用通配符)
- 运算符
- 算数运算符
- 比较运算符
- 逻辑运算符
- 函数
- 聚合函数
- 时间序列生成函数(包括内置函数和用户自定义函数)
- 常量
使用别名
由于 IoTDB 独特的数据模型,在每个传感器前都附带有设备等诸多额外信息。有时,我们只针对某个具体设备查询,而这些前缀信息频繁显示造成了冗余,影响了结果集的显示与分析。
IoTDB 支持使用AS为查询结果集中的列指定别名。
示例:
1. select s1 as temperature, s2 as speed from root.ln.wf01.wt01;
结果集将显示为:
| Time | temperature | speed |
|---|---|---|
| … | … | … |
运算符
IoTDB 中支持的运算符列表见文档 运算符和函数。
函数
聚合函数
聚合函数是多对一函数。它们对一组值进行聚合计算,得到单个聚合结果。
包含聚合函数的查询称为聚合查询,否则称为时间序列查询。
注意:聚合查询和时间序列查询不能混合使用。 下列语句是不支持的:
1. select s1, count(s1) from root.sg.d1;
2. select sin(s1), count(s1) from root.sg.d1;
3. select s1, count(s1) from root.sg.d1 group by ([10,100),10ms);
IoTDB 支持的聚合函数见文档 聚合函数。
时间序列生成函数
时间序列生成函数接受若干原始时间序列作为输入,产生一列时间序列输出。与聚合函数不同的是,时间序列生成函数的结果集带有时间戳列。
所有的时间序列生成函数都可以接受 * 作为输入,都可以与原始时间序列查询混合进行。
内置时间序列生成函数
IoTDB 中支持的内置函数列表见文档 运算符和函数。
自定义时间序列生成函数
IoTDB 支持通过用户自定义函数(点击查看: 用户自定义函数 )能力进行函数功能扩展。
嵌套表达式举例
IoTDB 支持嵌套表达式,由于聚合查询和时间序列查询不能在一条查询语句中同时出现,我们将支持的嵌套表达式分为时间序列查询嵌套表达式和聚合查询嵌套表达式两类。
时间序列查询嵌套表达式
IoTDB 支持在 SELECT 子句中计算由时间序列、常量、时间序列生成函数(包括用户自定义函数)和运算符组成的任意嵌套表达式。
说明:
- 当某个时间戳下左操作数和右操作数都不为空(
null)时,表达式才会有结果,否则表达式值为null,且默认不出现在结果集中。 - 如果表达式中某个操作数对应多条时间序列(如通配符
*),那么每条时间序列对应的结果都会出现在结果集中(按照笛卡尔积形式)。
示例 1:
1. select a,
2. b,
3. ((a + 1) * 2 - 1) % 2 + 1.5,
4. sin(a + sin(a + sin(b))),
5. -(a + b) * (sin(a + b) * sin(a + b) + cos(a + b) * cos(a + b)) + 1
6. from root.sg1;
运行结果:
1. +-----------------------------+----------+----------+----------------------------------------+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
2. | Time|root.sg1.a|root.sg1.b|((((root.sg1.a + 1) * 2) - 1) % 2) + 1.5|sin(root.sg1.a + sin(root.sg1.a + sin(root.sg1.b)))|(-root.sg1.a + root.sg1.b * ((sin(root.sg1.a + root.sg1.b) * sin(root.sg1.a + root.sg1.b)) + (cos(root.sg1.a + root.sg1.b) * cos(root.sg1.a + root.sg1.b)))) + 1|
3. +-----------------------------+----------+----------+----------------------------------------+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
4. |1970-01-01T08:00:00.010+08:00| 1| 1| 2.5| 0.9238430524420609| -1.0|
5. |1970-01-01T08:00:00.020+08:00| 2| 2| 2.5| 0.7903505371876317| -3.0|
6. |1970-01-01T08:00:00.030+08:00| 3| 3| 2.5| 0.14065207680386618| -5.0|
7. |1970-01-01T08:00:00.040+08:00| 4| null| 2.5| null| null|
8. |1970-01-01T08:00:00.050+08:00| null| 5| null| null| null|
9. |1970-01-01T08:00:00.060+08:00| 6| 6| 2.5| -0.7288037411970916| -11.0|
10. +-----------------------------+----------+----------+----------------------------------------+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
11. Total line number = 6
12. It costs 0.048s
示例 2:
1. select (a + b) * 2 + sin(a) from root.sg
运行结果:
1. +-----------------------------+----------------------------------------------+
2. | Time|((root.sg.a + root.sg.b) * 2) + sin(root.sg.a)|
3. +-----------------------------+----------------------------------------------+
4. |1970-01-01T08:00:00.010+08:00| 59.45597888911063|
5. |1970-01-01T08:00:00.020+08:00| 100.91294525072763|
6. |1970-01-01T08:00:00.030+08:00| 139.01196837590714|
7. |1970-01-01T08:00:00.040+08:00| 180.74511316047935|
8. |1970-01-01T08:00:00.050+08:00| 219.73762514629607|
9. |1970-01-01T08:00:00.060+08:00| 259.6951893788978|
10. |1970-01-01T08:00:00.070+08:00| 300.7738906815579|
11. |1970-01-01T08:00:00.090+08:00| 39.45597888911063|
12. |1970-01-01T08:00:00.100+08:00| 39.45597888911063|
13. +-----------------------------+----------------------------------------------+
14. Total line number = 9
15. It costs 0.011s
示例 3:
1. select (a + *) / 2 from root.sg1
运行结果:
1. +-----------------------------+-----------------------------+-----------------------------+
2. | Time|(root.sg1.a + root.sg1.a) / 2|(root.sg1.a + root.sg1.b) / 2|
3. +-----------------------------+-----------------------------+-----------------------------+
4. |1970-01-01T08:00:00.010+08:00| 1.0| 1.0|
5. |1970-01-01T08:00:00.020+08:00| 2.0| 2.0|
6. |1970-01-01T08:00:00.030+08:00| 3.0| 3.0|
7. |1970-01-01T08:00:00.040+08:00| 4.0| null|
8. |1970-01-01T08:00:00.060+08:00| 6.0| 6.0|
9. +-----------------------------+-----------------------------+-----------------------------+
10. Total line number = 5
11. It costs 0.011s
示例 4:
1. select (a + b) * 3 from root.sg, root.ln
运行结果:
1. +-----------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
2. | Time|(root.sg.a + root.sg.b) * 3|(root.sg.a + root.ln.b) * 3|(root.ln.a + root.sg.b) * 3|(root.ln.a + root.ln.b) * 3|
3. +-----------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
4. |1970-01-01T08:00:00.010+08:00| 90.0| 270.0| 360.0| 540.0|
5. |1970-01-01T08:00:00.020+08:00| 150.0| 330.0| 690.0| 870.0|
6. |1970-01-01T08:00:00.030+08:00| 210.0| 450.0| 570.0| 810.0|
7. |1970-01-01T08:00:00.040+08:00| 270.0| 240.0| 690.0| 660.0|
8. |1970-01-01T08:00:00.050+08:00| 330.0| null| null| null|
9. |1970-01-01T08:00:00.060+08:00| 390.0| null| null| null|
10. |1970-01-01T08:00:00.070+08:00| 450.0| null| null| null|
11. |1970-01-01T08:00:00.090+08:00| 60.0| null| null| null|
12. |1970-01-01T08:00:00.100+08:00| 60.0| null| null| null|
13. +-----------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
14. Total line number = 9
15. It costs 0.014s
聚合查询嵌套表达式
IoTDB 支持在 SELECT 子句中计算由聚合函数、常量、时间序列生成函数和表达式组成的任意嵌套表达式。
说明:
- 当某个时间戳下左操作数和右操作数都不为空(
null)时,表达式才会有结果,否则表达式值为null,且默认不出现在结果集中。但在使用GROUP BY子句的聚合查询嵌套表达式中,我们希望保留每个时间窗口的值,所以表达式值为null的窗口也包含在结果集中。 - 如果表达式中某个操作数对应多条时间序列(如通配符
*),那么每条时间序列对应的结果都会出现在结果集中(按照笛卡尔积形式)。
示例 1:
1. select avg(temperature),
2. sin(avg(temperature)),
3. avg(temperature) + 1,
4. -sum(hardware),
5. avg(temperature) + sum(hardware)
6. from root.ln.wf01.wt01;
运行结果:
1. +----------------------------------+---------------------------------------+--------------------------------------+--------------------------------+--------------------------------------------------------------------+
2. |avg(root.ln.wf01.wt01.temperature)|sin(avg(root.ln.wf01.wt01.temperature))|avg(root.ln.wf01.wt01.temperature) + 1|-sum(root.ln.wf01.wt01.hardware)|avg(root.ln.wf01.wt01.temperature) + sum(root.ln.wf01.wt01.hardware)|
3. +----------------------------------+---------------------------------------+--------------------------------------+--------------------------------+--------------------------------------------------------------------+
4. | 15.927999999999999| -0.21826546964855045| 16.927999999999997| -7426.0| 7441.928|
5. +----------------------------------+---------------------------------------+--------------------------------------+--------------------------------+--------------------------------------------------------------------+
6. Total line number = 1
7. It costs 0.009s
示例 2:
1. select avg(*),
2. (avg(*) + 1) * 3 / 2 -1
3. from root.sg1
运行结果:
1. +---------------+---------------+-------------------------------------+-------------------------------------+
2. |avg(root.sg1.a)|avg(root.sg1.b)|(avg(root.sg1.a) + 1) * 3 / 2 - 1 |(avg(root.sg1.b) + 1) * 3 / 2 - 1 |
3. +---------------+---------------+-------------------------------------+-------------------------------------+
4. | 3.2| 3.4| 5.300000000000001| 5.6000000000000005|
5. +---------------+---------------+-------------------------------------+-------------------------------------+
6. Total line number = 1
7. It costs 0.007s
示例 3:
1. select avg(temperature),
2. sin(avg(temperature)),
3. avg(temperature) + 1,
4. -sum(hardware),
5. avg(temperature) + sum(hardware) as custom_sum
6. from root.ln.wf01.wt01
7. GROUP BY([10, 90), 10ms);
运行结果:
1. +-----------------------------+----------------------------------+---------------------------------------+--------------------------------------+--------------------------------+----------+
2. | Time|avg(root.ln.wf01.wt01.temperature)|sin(avg(root.ln.wf01.wt01.temperature))|avg(root.ln.wf01.wt01.temperature) + 1|-sum(root.ln.wf01.wt01.hardware)|custom_sum|
3. +-----------------------------+----------------------------------+---------------------------------------+--------------------------------------+--------------------------------+----------+
4. |1970-01-01T08:00:00.010+08:00| 13.987499999999999| 0.9888207947857667| 14.987499999999999| -3211.0| 3224.9875|
5. |1970-01-01T08:00:00.020+08:00| 29.6| -0.9701057337071853| 30.6| -3720.0| 3749.6|
6. |1970-01-01T08:00:00.030+08:00| null| null| null| null| null|
7. |1970-01-01T08:00:00.040+08:00| null| null| null| null| null|
8. |1970-01-01T08:00:00.050+08:00| null| null| null| null| null|
9. |1970-01-01T08:00:00.060+08:00| null| null| null| null| null|
10. |1970-01-01T08:00:00.070+08:00| null| null| null| null| null|
11. |1970-01-01T08:00:00.080+08:00| null| null| null| null| null|
12. +-----------------------------+----------------------------------+---------------------------------------+--------------------------------------+--------------------------------+----------+
13. Total line number = 8
14. It costs 0.012s
最新点查询
最新点查询是时序数据库 Apache IoTDB 中提供的一种特殊查询。它返回指定时间序列中时间戳最大的数据点,即一条序列的最新状态。
在物联网数据分析场景中,此功能尤为重要。为了满足了用户对设备实时监控的需求,Apache IoTDB 对最新点查询进行了缓存优化,能够提供毫秒级的返回速度。
SQL 语法:
1. select last <Path> [COMMA <Path>]* from < PrefixPath > [COMMA < PrefixPath >]* <whereClause> [ORDER BY TIMESERIES (DESC | ASC)?]
其含义是: 查询时间序列 prefixPath.path 中最近时间戳的数据。
whereClause中当前只支持时间过滤条件,任何其他过滤条件都将会返回异常。当缓存的最新点不满足过滤条件时,IoTDB 需要从存储中获取结果,此时性能将会有所下降。- 结果集为四列的结构:
1. +----+----------+-----+--------+
2. |Time|timeseries|value|dataType|
3. +----+----------+-----+--------+
- 可以使用 ORDER BY TIME/TIMESERIES/VALUE/DATATYPE (DESC | ASC) 指定结果集按照某一列进行降序/升序排列。当值列包含多种类型的数据时,按照字符串类型来排序。
示例 1: 查询 root.ln.wf01.wt01.status 的最新数据点
1. IoTDB> select last status from root.ln.wf01.wt01
2. +-----------------------------+------------------------+-----+--------+
3. | Time| timeseries|value|dataType|
4. +-----------------------------+------------------------+-----+--------+
5. |2017-11-07T23:59:00.000+08:00|root.ln.wf01.wt01.status|false| BOOLEAN|
6. +-----------------------------+------------------------+-----+--------+
7. Total line number = 1
8. It costs 0.000s
示例 2: 查询 root.ln.wf01.wt01 下 status,temperature 时间戳大于等于 2017-11-07T23:50:00 的最新数据点。
1. IoTDB> select last status, temperature from root.ln.wf01.wt01 where time >= 2017-11-07T23:50:00
2. +-----------------------------+-----------------------------+---------+--------+
3. | Time| timeseries| value|dataType|
4. +-----------------------------+-----------------------------+---------+--------+
5. |2017-11-07T23:59:00.000+08:00| root.ln.wf01.wt01.status| false| BOOLEAN|
6. |2017-11-07T23:59:00.000+08:00|root.ln.wf01.wt01.temperature|21.067368| DOUBLE|
7. +-----------------------------+-----------------------------+---------+--------+
8. Total line number = 2
9. It costs 0.002s
示例 3: 查询 root.ln.wf01.wt01 下所有序列的最新数据点,并按照序列名降序排列。
1. IoTDB> select last * from root.ln.wf01.wt01 order by timeseries desc;
2. +-----------------------------+-----------------------------+---------+--------+
3. | Time| timeseries| value|dataType|
4. +-----------------------------+-----------------------------+---------+--------+
5. |2017-11-07T23:59:00.000+08:00|root.ln.wf01.wt01.temperature|21.067368| DOUBLE|
6. |2017-11-07T23:59:00.000+08:00| root.ln.wf01.wt01.status| false| BOOLEAN|
7. +-----------------------------+-----------------------------+---------+--------+
8. Total line number = 2
9. It costs 0.002s
示例 4: 查询 root.ln.wf01.wt01 下所有序列的最新数据点,并按照dataType降序排列。
1. IoTDB> select last * from root.ln.wf01.wt01 order by dataType desc;
2. +-----------------------------+-----------------------------+---------+--------+
3. | Time| timeseries| value|dataType|
4. +-----------------------------+-----------------------------+---------+--------+
5. |2017-11-07T23:59:00.000+08:00|root.ln.wf01.wt01.temperature|21.067368| DOUBLE|
6. |2017-11-07T23:59:00.000+08:00| root.ln.wf01.wt01.status| false| BOOLEAN|
7. +-----------------------------+-----------------------------+---------+--------+
8. Total line number = 2
9. It costs 0.002s
查询过滤条件(WHERE 子句)
WHERE 子句指定了对数据行的筛选条件,由一个 whereCondition 组成。
whereCondition 是一个逻辑表达式,对于要选择的每一行,其计算结果为真。如果没有 WHERE 子句,将选择所有行。
在 whereCondition 中,可以使用除聚合函数之外的任何 IOTDB 支持的函数和运算符。
根据过滤条件的不同,可以分为时间过滤条件和值过滤条件。时间过滤条件和值过滤条件可以混合使用。
时间过滤条件
使用时间过滤条件可以筛选特定时间范围的数据。对于时间戳支持的格式,请参考 时间戳类型 。
示例如下:
- 选择时间戳大于 2022-01-01T00:05:00.000 的数据:
1. select s1 from root.sg1.d1 where time > 2022-01-01T00:05:00.000;
2. 选择时间戳等于 2022-01-01T00:05:00.000 的数据:
1. select s1 from root.sg1.d1 where time = 2022-01-01T00:05:00.000;
3. 选择时间区间 [2017-11-01T00:05:00.000, 2017-11-01T00:12:00.000) 内的数据:
1. select s1 from root.sg1.d1 where time >= 2022-01-01T00:05:00.000 and time < 2017-11-01T00:12:00.000;
注:在上述示例中,time 也可写做 timestamp。
值过滤条件
使用值过滤条件可以筛选数据值满足特定条件的数据。 允许使用 select 子句中未选择的时间序列作为值过滤条件。
示例如下:
- 选择值大于 36.5 的数据:
1. select temperature from root.sg1.d1 where temperature > 36.5;
2. 选择值等于 true 的数据:
1. select status from root.sg1.d1 where status = true;
3. 选择区间 [36.5,40] 内或之外的数据:
1. select temperature from root.sg1.d1 where temperature between 36.5 and 40;
1. select temperature from root.sg1.d1 where temperature not between 36.5 and 40;
4. 选择值在特定范围内的数据:
1. select code from root.sg1.d1 where code in ('200', '300', '400', '500');
5. 选择值在特定范围外的数据:
1. select code from root.sg1.d1 where code not in ('200', '300', '400', '500');
6. 选择值为空的数据:
1. select code from root.sg1.d1 where temperature is null;
7. 选择值为非空的数据:
1. select code from root.sg1.d1 where temperature is not null;
模糊查询
对于 TEXT 类型的数据,支持使用 Like 和 Regexp 运算符对数据进行模糊匹配
使用 Like 进行模糊匹配
匹配规则:
%表示任意0个或多个字符。_表示任意单个字符。
示例 1: 查询 root.sg.d1 下 value 含有'cc'的数据。
1. IoTDB> select * from root.sg.d1 where value like '%cc%'
2. +-----------------------------+----------------+
3. | Time|root.sg.d1.value|
4. +-----------------------------+----------------+
5. |2017-11-01T00:00:00.000+08:00| aabbccdd|
6. |2017-11-01T00:00:01.000+08:00| cc|
7. +-----------------------------+----------------+
8. Total line number = 2
9. It costs 0.002s
示例 2: 查询 root.sg.d1 下 value 中间为 'b'、前后为任意单个字符的数据。
1. IoTDB> select * from root.sg.device where value like '_b_'
2. +-----------------------------+----------------+
3. | Time|root.sg.d1.value|
4. +-----------------------------+----------------+
5. |2017-11-01T00:00:02.000+08:00| abc|
6. +-----------------------------+----------------+
7. Total line number = 1
8. It costs 0.002s
使用 Regexp 进行模糊匹配
需要传入的过滤条件为 Java 标准库风格的正则表达式。
常见的正则匹配举例:
1. 长度为3-20的所有字符:^.{3,20}$
2. 大写英文字符:^[A-Z]+$
3. 数字和英文字符:^[A-Za-z0-9]+$
4. 以a开头的:^a.*
示例 1: 查询 root.sg.d1 下 value 值为26个英文字符组成的字符串。
1. IoTDB> select * from root.sg.d1 where value regexp '^[A-Za-z]+$'
2. +-----------------------------+----------------+
3. | Time|root.sg.d1.value|
4. +-----------------------------+----------------+
5. |2017-11-01T00:00:00.000+08:00| aabbccdd|
6. |2017-11-01T00:00:01.000+08:00| cc|
7. +-----------------------------+----------------+
8. Total line number = 2
9. It costs 0.002s
示例 2: 查询 root.sg.d1 下 value 值为26个小写英文字符组成的字符串且时间大于100的。
1. IoTDB> select * from root.sg.d1 where value regexp '^[a-z]+$' and time > 100
2. +-----------------------------+----------------+
3. | Time|root.sg.d1.value|
4. +-----------------------------+----------------+
5. |2017-11-01T00:00:00.000+08:00| aabbccdd|
6. |2017-11-01T00:00:01.000+08:00| cc|
7. +-----------------------------+----------------+
8. Total line number = 2
9. It costs 0.002s
分段分组聚合(GROUP BY 子句)
IoTDB支持通过GROUP BY子句对序列进行分段或者分组聚合。
分段聚合是指按照时间维度,针对同时间序列中不同数据点之间的时间关系,对数据在行的方向进行分段,每个段得到一个聚合值。目前支持时间区间分段、差值分段、条件分段、会话分段和点数分段,未来将支持更多分段方式。
分组聚合是指针对不同时间序列,在时间序列的潜在业务属性上分组,每个组包含若干条时间序列,每个组得到一个聚合值。支持按路径层级分组和按序列标签分组两种分组方式。
分段聚合
时间区间分段聚合
时间区间分段聚合是一种时序数据典型的查询方式,数据以高频进行采集,需要按照一定的时间间隔进行聚合计算,如计算每天的平均气温,需要将气温的序列按天进行分段,然后计算平均值。
在 IoTDB 中,聚合查询可以通过 GROUP BY 子句指定按照时间区间分段聚合。用户可以指定聚合的时间间隔和滑动步长,相关参数如下:
- 参数 1:时间轴显示时间窗口大小
- 参数 2:聚合窗口的大小(必须为正数)
- 参数 3:聚合窗口的滑动步长(可选,默认与聚合窗口大小相同)
下图中指出了这三个参数的含义:

接下来,我们给出几个典型例子:
未指定滑动步长的时间区间分段聚合查询
对应的 SQL 语句是:
1. select count(status), max_value(temperature) from root.ln.wf01.wt01 group by ([2017-11-01T00:00:00, 2017-11-07T23:00:00),1d);
这条查询的含义是:
由于用户没有指定滑动步长,滑动步长将会被默认设置为跟时间间隔参数相同,也就是1d。
上面这个例子的第一个参数是显示窗口参数,决定了最终的显示范围是 [2017-11-01T00:00:00, 2017-11-07T23:00:00)。
上面这个例子的第二个参数是划分时间轴的时间间隔参数,将1d当作划分间隔,显示窗口参数的起始时间当作分割原点,时间轴即被划分为连续的时间间隔:[0,1d), [1d, 2d), [2d, 3d) 等等。
然后系统将会用 WHERE 子句中的时间和值过滤条件以及 GROUP BY 语句中的第一个参数作为数据的联合过滤条件,获得满足所有过滤条件的数据(在这个例子里是在 [2017-11-01T00:00:00, 2017-11-07 T23:00:00) 这个时间范围的数据),并把这些数据映射到之前分割好的时间轴中(这个例子里是从 2017-11-01T00:00:00 到 2017-11-07T23:00:00:00 的每一天)
每个时间间隔窗口内都有数据,SQL 执行后的结果集如下所示:
1. +-----------------------------+-------------------------------+----------------------------------------+
2. | Time|count(root.ln.wf01.wt01.status)|max_value(root.ln.wf01.wt01.temperature)|
3. +-----------------------------+-------------------------------+----------------------------------------+
4. |2017-11-01T00:00:00.000+08:00| 1440| 26.0|
5. |2017-11-02T00:00:00.000+08:00| 1440| 26.0|
6. |2017-11-03T00:00:00.000+08:00| 1440| 25.99|
7. |2017-11-04T00:00:00.000+08:00| 1440| 26.0|
8. |2017-11-05T00:00:00.000+08:00| 1440| 26.0|
9. |2017-11-06T00:00:00.000+08:00| 1440| 25.99|
10. |2017-11-07T00:00:00.000+08:00| 1380| 26.0|
11. +-----------------------------+-------------------------------+----------------------------------------+
12. Total line number = 7
13. It costs 0.024s
指定滑动步长的时间区间分段聚合查询
对应的 SQL 语句是:
1. select count(status), max_value(temperature) from root.ln.wf01.wt01 group by ([2017-11-01 00:00:00, 2017-11-07 23:00:00), 3h, 1d);
这条查询的含义是:
由于用户指定了滑动步长为1d,GROUP BY 语句执行时将会每次把时间间隔往后移动一天的步长,而不是默认的 3 小时。
也就意味着,我们想要取从 2017-11-01 到 2017-11-07 每一天的凌晨 0 点到凌晨 3 点的数据。
上面这个例子的第一个参数是显示窗口参数,决定了最终的显示范围是 [2017-11-01T00:00:00, 2017-11-07T23:00:00)。
上面这个例子的第二个参数是划分时间轴的时间间隔参数,将3h当作划分间隔,显示窗口参数的起始时间当作分割原点,时间轴即被划分为连续的时间间隔:[2017-11-01T00:00:00, 2017-11-01T03:00:00), [2017-11-02T00:00:00, 2017-11-02T03:00:00), [2017-11-03T00:00:00, 2017-11-03T03:00:00) 等等。
上面这个例子的第三个参数是每次时间间隔的滑动步长。
然后系统将会用 WHERE 子句中的时间和值过滤条件以及 GROUP BY 语句中的第一个参数作为数据的联合过滤条件,获得满足所有过滤条件的数据(在这个例子里是在 [2017-11-01T00:00:00, 2017-11-07 T23:00:00) 这个时间范围的数据),并把这些数据映射到之前分割好的时间轴中(这个例子里是从 2017-11-01T00:00:00 到 2017-11-07T23:00:00:00 的每一天的凌晨 0 点到凌晨 3 点)
每个时间间隔窗口内都有数据,SQL 执行后的结果集如下所示:
1. +-----------------------------+-------------------------------+----------------------------------------+
2. | Time|count(root.ln.wf01.wt01.status)|max_value(root.ln.wf01.wt01.temperature)|
3. +-----------------------------+-------------------------------+----------------------------------------+
4. |2017-11-01T00:00:00.000+08:00| 180| 25.98|
5. |2017-11-02T00:00:00.000+08:00| 180| 25.98|
6. |2017-11-03T00:00:00.000+08:00| 180| 25.96|
7. |2017-11-04T00:00:00.000+08:00| 180| 25.96|
8. |2017-11-05T00:00:00.000+08:00| 180| 26.0|
9. |2017-11-06T00:00:00.000+08:00| 180| 25.85|
10. |2017-11-07T00:00:00.000+08:00| 180| 25.99|
11. +-----------------------------+-------------------------------+----------------------------------------+
12. Total line number = 7
13. It costs 0.006s
滑动步长可以小于聚合窗口,此时聚合窗口之间有重叠时间(类似于一个滑动窗口)。
例如 SQL:
1. select count(status), max_value(temperature) from root.ln.wf01.wt01 group by ([2017-11-01 00:00:00, 2017-11-01 10:00:00), 4h, 2h);
SQL 执行后的结果集如下所示:
1. +-----------------------------+-------------------------------+----------------------------------------+
2. | Time|count(root.ln.wf01.wt01.status)|max_value(root.ln.wf01.wt01.temperature)|
3. +-----------------------------+-------------------------------+----------------------------------------+
4. |2017-11-01T00:00:00.000+08:00| 180| 25.98|
5. |2017-11-01T02:00:00.000+08:00| 180| 25.98|
6. |2017-11-01T04:00:00.000+08:00| 180| 25.96|
7. |2017-11-01T06:00:00.000+08:00| 180| 25.96|
8. |2017-11-01T08:00:00.000+08:00| 180| 26.0|
9. +-----------------------------+-------------------------------+----------------------------------------+
10. Total line number = 5
11. It costs 0.006s
按照自然月份的时间区间分段聚合查询
对应的 SQL 语句是:
1. select count(status) from root.ln.wf01.wt01 where time > 2017-11-01T01:00:00 group by([2017-11-01T00:00:00, 2019-11-07T23:00:00), 1mo, 2mo);
这条查询的含义是:
由于用户指定了滑动步长为2mo,GROUP BY 语句执行时将会每次把时间间隔往后移动 2 个自然月的步长,而不是默认的 1 个自然月。
也就意味着,我们想要取从 2017-11-01 到 2019-11-07 每 2 个自然月的第一个月的数据。
上面这个例子的第一个参数是显示窗口参数,决定了最终的显示范围是 [2017-11-01T00:00:00, 2019-11-07T23:00:00)。
起始时间为 2017-11-01T00:00:00,滑动步长将会以起始时间作为标准按月递增,取当月的 1 号作为时间间隔的起始时间。
上面这个例子的第二个参数是划分时间轴的时间间隔参数,将1mo当作划分间隔,显示窗口参数的起始时间当作分割原点,时间轴即被划分为连续的时间间隔:[2017-11-01T00:00:00, 2017-12-01T00:00:00), [2018-02-01T00:00:00, 2018-03-01T00:00:00), [2018-05-03T00:00:00, 2018-06-01T00:00:00) 等等。
上面这个例子的第三个参数是每次时间间隔的滑动步长。
然后系统将会用 WHERE 子句中的时间和值过滤条件以及 GROUP BY 语句中的第一个参数作为数据的联合过滤条件,获得满足所有过滤条件的数据(在这个例子里是在 [2017-11-01T00:00:00, 2019-11-07T23:00:00) 这个时间范围的数据),并把这些数据映射到之前分割好的时间轴中(这个例子里是从 2017-11-01T00:00:00 到 2019-11-07T23:00:00:00 的每两个自然月的第一个月)
每个时间间隔窗口内都有数据,SQL 执行后的结果集如下所示:
1. +-----------------------------+-------------------------------+
2. | Time|count(root.ln.wf01.wt01.status)|
3. +-----------------------------+-------------------------------+
4. |2017-11-01T00:00:00.000+08:00| 259|
5. |2018-01-01T00:00:00.000+08:00| 250|
6. |2018-03-01T00:00:00.000+08:00| 259|
7. |2018-05-01T00:00:00.000+08:00| 251|
8. |2018-07-01T00:00:00.000+08:00| 242|
9. |2018-09-01T00:00:00.000+08:00| 225|
10. |2018-11-01T00:00:00.000+08:00| 216|
11. |2019-01-01T00:00:00.000+08:00| 207|
12. |2019-03-01T00:00:00.000+08:00| 216|
13. |2019-05-01T00:00:00.000+08:00| 207|
14. |2019-07-01T00:00:00.000+08:00| 199|
15. |2019-09-01T00:00:00.000+08:00| 181|
16. |2019-11-01T00:00:00.000+08:00| 60|
17. +-----------------------------+-------------------------------+
对应的 SQL 语句是:
1. select count(status) from root.ln.wf01.wt01 group by([2017-10-31T00:00:00, 2019-11-07T23:00:00), 1mo, 2mo);
这条查询的含义是:
由于用户指定了滑动步长为2mo,GROUP BY 语句执行时将会每次把时间间隔往后移动 2 个自然月的步长,而不是默认的 1 个自然月。
也就意味着,我们想要取从 2017-10-31 到 2019-11-07 每 2 个自然月的第一个月的数据。
与上述示例不同的是起始时间为 2017-10-31T00:00:00,滑动步长将会以起始时间作为标准按月递增,取当月的 31 号(即最后一天)作为时间间隔的起始时间。若起始时间设置为 30 号,滑动步长会将时间间隔的起始时间设置为当月 30 号,若不存在则为最后一天。
上面这个例子的第一个参数是显示窗口参数,决定了最终的显示范围是 [2017-10-31T00:00:00, 2019-11-07T23:00:00)。
上面这个例子的第二个参数是划分时间轴的时间间隔参数,将1mo当作划分间隔,显示窗口参数的起始时间当作分割原点,时间轴即被划分为连续的时间间隔:[2017-10-31T00:00:00, 2017-11-31T00:00:00), [2018-02-31T00:00:00, 2018-03-31T00:00:00), [2018-05-31T00:00:00, 2018-06-31T00:00:00) 等等。
上面这个例子的第三个参数是每次时间间隔的滑动步长。
然后系统将会用 WHERE 子句中的时间和值过滤条件以及 GROUP BY 语句中的第一个参数作为数据的联合过滤条件,获得满足所有过滤条件的数据(在这个例子里是在 [2017-10-31T00:00:00, 2019-11-07T23:00:00) 这个时间范围的数据),并把这些数据映射到之前分割好的时间轴中(这个例子里是从 2017-10-31T00:00:00 到 2019-11-07T23:00:00:00 的每两个自然月的第一个月)
每个时间间隔窗口内都有数据,SQL 执行后的结果集如下所示:
1. +-----------------------------+-------------------------------+
2. | Time|count(root.ln.wf01.wt01.status)|
3. +-----------------------------+-------------------------------+
4. |2017-10-31T00:00:00.000+08:00| 251|
5. |2017-12-31T00:00:00.000+08:00| 250|
6. |2018-02-28T00:00:00.000+08:00| 259|
7. |2018-04-30T00:00:00.000+08:00| 250|
8. |2018-06-30T00:00:00.000+08:00| 242|
9. |2018-08-31T00:00:00.000+08:00| 225|
10. |2018-10-31T00:00:00.000+08:00| 216|
11. |2018-12-31T00:00:00.000+08:00| 208|
12. |2019-02-28T00:00:00.000+08:00| 216|
13. |2019-04-30T00:00:00.000+08:00| 208|
14. |2019-06-30T00:00:00.000+08:00| 199|
15. |2019-08-31T00:00:00.000+08:00| 181|
16. |2019-10-31T00:00:00.000+08:00| 69|
17. +-----------------------------+-------------------------------+
左开右闭区间
每个区间的结果时间戳为区间右端点,对应的 SQL 语句是:
1. select count(status) from root.ln.wf01.wt01 group by ((2017-11-01T00:00:00, 2017-11-07T23:00:00],1d);
这条查询语句的时间区间是左开右闭的,结果中不会包含时间点 2017-11-01 的数据,但是会包含时间点 2017-11-07 的数据。
SQL 执行后的结果集如下所示:
``` 1. +-----------------------------+-------------------------------+ 2. | Time|count(root.ln.wf01.wt01.status)| 3. +-----------------------------+-------------------------------+ 4. |2017-11-02T00:00:00.000+08:00| 1440| 5. |2017-11-03T00:00:00.000+08:00| 1440| 6. |2017-11-04T00:00:00.000+08:00| 1440| 7. |2017-11-05T00:00:00.000+08:00| 1440| 8. |2017-11-06T00:00:00.000+08:00| 1440| 9. |2017-11-07T00:00:00.000+08:00| 1440| 10. |2017-11-07T23:00:00.000+08:00|
(本文超出站点单文档体积上限,已截断)
