【influxdb3】如何使用 SQL 对时间序列数据进行聚合查询
学习如何使用 SQL 对时间序列数据进行聚合查询,尤其是结合 InfluxDB 3 使用场景:
使用 SQL 聚合数据
一个用于聚合数据的 SQL 查询通常包含以下子句:
- 必填
- SELECT:指定要从表中输出的字段、标签和计算结果;或者使用通配符
(*)
来选择表中的所有字段和标签。 - FROM:指定要查询数据的表。
- WHERE:仅返回满足特定条件的行。例如:时间在某个时间范围内、某个标签具有特定值、或某个字段值高于/低于指定阈值。
- GROUP BY:将具有相同列值或表达式结果的数据分组。例如:对某个聚合函数的结果进行分组。
为简化描述,在本文中,“聚合”一词泛指对数据集应用聚合函数和选择器函数。
以下是教你如何对查询数据应用聚合操作的内容:
- 聚合函数与选择器函数
- 聚合函数
- 选择器函数
- 示例聚合查询
聚合函数与选择器函数
无论是聚合函数还是选择器函数,它们都会从每个 SQL 分组中返回一行结果。例如,如果你使用 GROUP BY room
并在 SELECT
子句中执行一个聚合操作,则结果会包含每个唯一 room
值对应的聚合值。
聚合函数
使用聚合函数来对每组数据中指定列的值进行聚合,并为每组返回一行包含聚合后的值。
查看 SQL 聚合函数列表
函数 | 描述 |
---|---|
AVG(column) | 返回列的平均值 |
SUM(column) | 返回列的总和 |
MIN(column) | 返回列的最小值 |
MAX(column) | 返回列的最大值 |
COUNT(column) | 统计非空值的数量 |
简单聚合查询示例:
SELECT AVG(co) FROM home
选择器函数(Selector Functions)
使用选择器函数来“选择”某列中的一个值。这些函数专为时间序列数据设计。
查看 SQL 选择器函数列表
函数 | 描述 |
---|---|
selector_first(value_col, time_col) | 返回该组中最早时间点的值 |
selector_last(value_col, time_col) | 返回该组中最新时间点的值 |
selector_min(value_col, time_col) | 返回该组中值最小的那一行的值 |
selector_max(value_col, time_col) | 返回该组中值最大的那一行的值 |
选择器结构体格式
选择器函数返回一个类似 JSON 的结构体(Rust Struct),表示某组中选中的一个时间和值。返回的时间和值取决于函数逻辑。例如:
{time: "2023-01-01T00:00:00Z", value: 72.1}
使用选择器函数
每个选择器函数有两个参数:
- 第一个是你要操作的数值列;
- 第二个是用于选择逻辑的时间列。
在 SELECT
子句中执行选择器函数时,可以使用方括号访问结构体的属性:
SELECTselector_first(temp, time)['time'] AS time,selector_first(temp, time)['value'] AS temp,room
FROM home
GROUP BY room
示例聚合查询
执行无分组的聚合
要对指定列中的所有查询值进行聚合:
- 在
SELECT
子句中使用聚合函数或选择器函数; - 不使用
GROUP BY
子句,以避免对数据进行分组。
SELECT avg(co) AS 'average co' FROM home
对分组数据进行聚合
要对分组数据应用聚合或选择器函数:
- 在
SELECT
子句中使用聚合或选择器函数; - 在
SELECT
子句中列出你希望按其分组的列; - 在
GROUP BY
子句中使用逗号分隔的列名或表达式进行分组。
注意:
GROUP BY
可以使用SELECT
子句中定义的别名;- 如果别名与原始列名相同,
GROUP BY
将忽略别名并使用原始列值。
SELECTroom,avg(temp) AS 'average temp'
FROM home
GROUP BY room
按时间间隔下采样数据(Downsampling)
在时间序列数据中,常见的用例是对数据进行按时间区间的聚合。要实现这一点:
- 在
SELECT
子句中使用DATE_BIN
函数来计算时间间隔,并生成一个新的时间列; - 使用聚合或选择器函数处理其他列;
- 在
GROUP BY
子句中引用DATE_BIN(...)
结果(可以通过序号或别名); - 添加
ORDER BY
子句来排序结果。
SELECTDATE_BIN(INTERVAL '2 hours', time) AS time,room,selector_max(temp, time)['value'] AS 'max temp',selector_min(temp, time)['value'] AS 'min temp',avg(temp) AS 'average temp'
FROM home
GROUP BY 1, room
ORDER BY room, 1
💡 提示:如果在
GROUP BY
中引用DATE_BIN(...)
列,请不要使用time
作为别名,否则可能混淆源表的time
字段。建议使用_time
或其他名称。
根据聚合值筛选数据
要在聚合后根据值进行筛选,可以使用 HAVING
子句,它会在数据聚合之后应用条件过滤。
WHERE
子句在聚合前应用过滤;HAVING
子句在聚合后应用过滤。
SELECTroom,avg(co) AS 'average co'
FROM home
GROUP BY room
HAVING "average co" > 5
📌 总结
子句 | 用途 |
---|---|
SELECT | 指定输出字段和聚合函数 |
FROM | 指定查询来源的表 |
WHERE | 在聚合前过滤数据 |
GROUP BY | 按照指定列进行分组 |
HAVING | 在聚合后过滤分组结果 |
DATE_BIN() | 实现基于时间窗口的下采样 |
selector_*() | 选择特定时间点的值(如最早、最晚、最大、最小等) |
✅ 最佳实践建议
- ✅ 使用双引号包裹所有表名和字段名,保留大小写敏感性;
- ✅ 避免在
GROUP BY
中使用与原列同名的别名; - ✅ 时间列重命名推荐使用
_time
等新名称; - ✅ 在 Grafana 中连接 InfluxDB 3 时,使用 PostgreSQL 数据源插件;
- ✅ 使用标准 SQL 语法替代 InfluxQL 特有结构。