文档文档

在 SQL 查询中比较值

使用 SQL 窗口函数来比较时序数据中不同行之间的值。诸如 LAGLEAD 这样的窗口函数,让您无需使用自连接即可访问前一行或后一行中的值,从而轻松计算随时间的变化。

比较值的常见用例包括:

  • 计算当前值与前一个值之间的差值
  • 计算变化率或百分比变化
  • 检测显著变化或异常
  • 比较特定时间间隔内的值
  • 处理重置为零的计数器指标

要跨行比较值,请执行以下操作:

  1. 使用带有 OVER 子句的 窗口函数,例如 LAGLEAD
  2. 包含 PARTITION BY 子句,按标签(如 roomsensor_id)对数据进行分组。
  3. 包含 ORDER BY 子句,以定义比较顺序(通常按 time)。
  4. 使用算术运算符计算差值、比率或百分比变化。

比较值的示例

示例数据

以下示例使用 家庭传感器示例数据。要在运行示例查询之前运行查询并返回结果,请 将示例数据写入 InfluxDB 3 Core 数据库。

计算与前一个值的差值

使用 LAG 函数访问前一行中的值并计算差值。这对于检测随时间的变化很有用。

SELECT
  time,
  room,
  temp,
  temp - LAG(temp, 1) OVER (
    PARTITION BY room
    ORDER BY time
  ) AS temp_change
FROM home
WHERE
  time >= '2022-01-01T08:00:00Z'
  AND time < '2022-01-01T11:00:00Z'
ORDER BY room, time
timeroomtemptemp_change
2022-01-01T08:00:00厨房21.0NULL
2022-01-01T09:00:00厨房23.02.0
2022-01-01T10:00:00厨房22.7-0.3
2022-01-01T08:00:00客厅21.1NULL
2022-01-01T09:00:00客厅21.40.3
2022-01-01T10:00:00客厅21.80.4

每个分区中的第一行对于 temp_change 返回 NULL,因为没有前一个值。要使用默认值而不是 NULL,请向 LAG 提供第三个参数。

LAG(temp, 1, 0) -- Returns 0 if no previous value exists

计算百分比变化

通过将差值除以前一个值来计算当前值与前一个值之间的百分比变化。

SELECT
  time,
  room,
  temp,
  ROUND(
    ((temp - LAG(temp, 1) OVER (PARTITION BY room ORDER BY time)) /
     LAG(temp, 1) OVER (PARTITION BY room ORDER BY time)) * 100,
    2
  ) AS percent_change
FROM home
WHERE
  time >= '2022-01-01T08:00:00Z'
  AND time < '2022-01-01T11:00:00Z'
ORDER BY room, time
timeroomtemppercent_change
2022-01-01T08:00:00厨房21.0NULL
2022-01-01T09:00:00厨房23.09.52
2022-01-01T10:00:00厨房22.7-1.30
2022-01-01T08:00:00客厅21.1NULL
2022-01-01T09:00:00客厅21.41.42
2022-01-01T10:00:00客厅21.81.87

比较固定间隔的值

对于固定间隔的时序数据(如每小时的读数),请使用带有偏移量参数的 LAG 来比较 N 行之前的值。

以下查询将每个温度读数与一小时前(假设为每小时数据)的读数进行比较。

SELECT
  time,
  room,
  temp,
  LAG(temp, 1) OVER (
    PARTITION BY room
    ORDER BY time
  ) AS temp_1h_ago,
  temp - LAG(temp, 1) OVER (
    PARTITION BY room
    ORDER BY time
  ) AS hourly_change
FROM home
WHERE
  time >= '2022-01-01T08:00:00Z'
  AND time < '2022-01-01T12:00:00Z'
ORDER BY room, time
timeroomtemptemp_1h_agohourly_change
2022-01-01T08:00:00厨房21.0NULLNULL
2022-01-01T09:00:00厨房23.021.02.0
2022-01-01T10:00:00厨房22.723.0-0.3
2022-01-01T11:00:00厨房22.422.7-0.3
2022-01-01T08:00:00客厅21.1NULLNULL
2022-01-01T09:00:00客厅21.421.10.3
2022-01-01T10:00:00客厅21.821.40.4
2022-01-01T11:00:00客厅22.221.80.4

比较具有精确时间偏移的值

对于不规则间隔的时序数据,或当您需要与精确时间偏移(例如,正好一小时前,而不仅仅是前一行)进行比较时,请使用带有间隔算术的自连接。

SELECT
  current.time,
  current.room,
  current.temp AS current_temp,
  previous.temp AS temp_1h_ago,
  current.temp - previous.temp AS hourly_diff
FROM home AS current
LEFT JOIN home AS previous
  ON current.room = previous.room
  AND previous.time = current.time - INTERVAL '1 hour'
WHERE
  current.time >= '2022-01-01T08:00:00Z'
  AND current.time < '2022-01-01T12:00:00Z'
ORDER BY current.room, current.time
timeroomcurrent_temptemp_1h_agohourly_diff
2022-01-01T08:00:00厨房21.0NULLNULL
2022-01-01T09:00:00厨房23.021.02.0
2022-01-01T10:00:00厨房22.723.0-0.3
2022-01-01T11:00:00厨房22.422.7-0.3
2022-01-01T08:00:00客厅21.1NULLNULL
2022-01-01T09:00:00客厅21.421.10.3
2022-01-01T10:00:00客厅21.821.40.4
2022-01-01T11:00:00客厅22.221.80.4

这种自连接方法在以下情况下有效:

  • 您的数据点不以固定的间隔出现
  • 您需要与特定的时间偏移进行比较,而不管上一个数据点何时发生
  • 您想确保比较的是正好一小时前(或任何其他特定间隔)的值

处理计数器指标和重置

计数器指标跟踪随时间增加的累积值,例如总请求数、传输的字节数或错误数。与仪表指标(可以上升或下降)不同,计数器通常只增加,尽管它们在服务重新启动时可能会重置为零。

使用 GREATESTLAG 来处理计数器重置,方法是将负差值视为零。

InfluxDB 3 SQL 和计数器指标

InfluxDB 3 SQL 不提供 Flux 的 increase() 或 InfluxQL 的 NON_NEGATIVE_DIFFERENCE() 函数的内置等效项。使用下面显示的模式来实现类似的结果。

计算非负差值(计数器速率)

计算连续计数器读数之间的增加量,将负差值(计数器重置)视为零。

SELECT
  time,
  host,
  requests,
  LAG(requests) OVER (PARTITION BY host ORDER BY time) AS prev_requests,
  GREATEST(
    requests - LAG(requests) OVER (PARTITION BY host ORDER BY time),
    0
  ) AS requests_increase
FROM metrics
WHERE host = 'server1'
ORDER BY time
timehostrequestsprev_requestsrequests_increase
2024-01-01T00:00:00server11000NULL0
2024-01-01T01:00:00server112501000250
2024-01-01T02:00:00server116001250350
2024-01-01T03:00:00server15016000
2024-01-01T04:00:00server130050250

LAG(requests) 检索前一个计数器值,requests - LAG(requests) 计算差值,GREATEST(..., 0) 为负差值(计数器重置)返回 0。PARTITION BY host 确保仅在同一主机内进行比较。

计算累积计数器增加量

计算计数器随时间的总增加量,并处理重置。使用公用表表达式 (CTE) 先计算差值,然后将它们相加。

WITH counter_diffs AS (
  SELECT
    time,
    host,
    requests,
    GREATEST(
      requests - LAG(requests) OVER (PARTITION BY host ORDER BY time),
      0
    ) AS requests_increase
  FROM metrics
  WHERE host = 'server1'
)
SELECT
  time,
  host,
  requests,
  SUM(requests_increase) OVER (PARTITION BY host ORDER BY time) AS cumulative_increase
FROM counter_diffs
ORDER BY time
timehostrequestscumulative_increase
2024-01-01T00:00:00server110000
2024-01-01T01:00:00server11250250
2024-01-01T02:00:00server11600600
2024-01-01T03:00:00server150600
2024-01-01T04:00:00server1300850

CTE 计算每一行的非负差值,然后 SUM(requests_increase) OVER (...) 创建一个运行总计。尽管在 03:00 发生计数器重置,但累积增加量仍在增长。

按时间间隔聚合计数器增加量

计算每个时间间隔(例如,每小时总计)的计数器总增加量。

WITH counter_diffs AS (
  SELECT
    DATE_BIN(INTERVAL '1 hour', time) AS time_bucket,
    host,
    requests,
    GREATEST(
      requests - LAG(requests) OVER (PARTITION BY host ORDER BY time),
      0
    ) AS requests_increase
  FROM metrics
)
SELECT
  time_bucket,
  host,
  SUM(requests_increase) AS total_increase
FROM counter_diffs
WHERE requests_increase > 0
GROUP BY time_bucket, host
ORDER BY host, time_bucket
time_buckethosttotal_increase
2024-01-01T01:00:00server1250
2024-01-01T02:00:00server1350
2024-01-01T04:00:00server1250
2024-01-01T01:00:00server2400
2024-01-01T02:00:00server2500
2024-01-01T03:00:00server2300
2024-01-01T04:00:00server2400

CTE 计算每一行的差值。DATE_BIN() 将每个时间戳分配到一个 1 小时的时间间隔,SUM(requests_increase) 聚合每个间隔内的所有增加量,而 WHERE requests_increase > 0 过滤掉零增加量(第一行和计数器重置)。


此页面是否有帮助?

感谢您的反馈!


InfluxDB 3.8 新特性

InfluxDB 3.8 和 InfluxDB 3 Explorer 1.6 的主要增强功能。

查看博客文章

InfluxDB 3.8 现已适用于 Core 和 Enterprise 版本,同时发布了 InfluxDB 3 Explorer UI 的 1.6 版本。本次发布着重于操作成熟度,以及如何更轻松地部署、管理和可靠地运行 InfluxDB。

更多信息,请查看

InfluxDB Docker 的 latest 标签将指向 InfluxDB 3 Core

在 **2026 年 2 月 3 日**,InfluxDB Docker 镜像的 latest 标签将指向 InfluxDB 3 Core。为避免意外升级,请在您的 Docker 部署中使用特定的版本标签。

如果使用 Docker 来安装和运行 InfluxDB,latest 标签将指向 InfluxDB 3 Core。为避免意外升级,请在您的 Docker 部署中使用特定的版本标签。例如,如果使用 Docker 运行 InfluxDB v2,请将 latest 版本标签替换为 Docker pull 命令中的特定版本标签 — 例如

docker pull influxdb:2