【influxdb3】如何使用 SQL 对时间序列数据进行聚合查询

发布于:2025-07-07 ⋅ 阅读:(17) ⋅ 点赞:(0)

学习如何使用 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}
使用选择器函数

每个选择器函数有两个参数:

  1. 第一个是你要操作的数值列;
  2. 第二个是用于选择逻辑的时间列。

SELECT 子句中执行选择器函数时,可以使用方括号访问结构体的属性:

SELECT
  selector_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 将忽略别名并使用原始列值。
SELECT
  room,
  avg(temp) AS 'average temp'
FROM home
GROUP BY room

按时间间隔下采样数据(Downsampling)

在时间序列数据中,常见的用例是对数据进行按时间区间的聚合。要实现这一点:

  • SELECT 子句中使用 DATE_BIN 函数来计算时间间隔,并生成一个新的时间列;
  • 使用聚合或选择器函数处理其他列;
  • GROUP BY 子句中引用 DATE_BIN(...) 结果(可以通过序号或别名);
  • 添加 ORDER BY 子句来排序结果。
SELECT
  DATE_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 子句在聚合后应用过滤。
SELECT
  room,
  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 特有结构。