有一个表存储汽车的名称、速度和时间戳。每辆车以不规则的时间间隔发送其速度,有些发送更频繁,有些可能几个小时没有发送数据,简化示例(真实表有 20 辆车,每辆车大约 3000 行):
名字 | 速度 | 时间戳 |
---|---|---|
黄色 | 100 | 1707532681 |
黄色 | 110 | 1707532661 |
黄色 | 120 | 1707532621 |
黄色 | 110 | 1707532631 |
黄色 | 140 | 1707532681 |
红色 | 100 | 1707432681 |
红色 | 120 | 1707332681 |
红色 | 150 | 1707232681 |
红色 | 170 | 1707532681 |
我想获得每辆车过去 24 小时内(!)的平均速度。我正在努力将其放入单个 SQL 语句中。尝试过多个 SELECT 和 IN、MAX 和 AVG 函数,但没有成功。如有任何帮助,我们将不胜感激。
我尝试获取每辆车的最大值: SELECT name, MAX(timestamp) AS FROM data GROUP BY name
并将其放入另一个 SELECT 中: SELECT AVG(speed) FROM data WHERE (name, timestamp) IN (SELECT name, MAX(timestamp) AS s FROM data GROUP BY name) AND timestamp > s - 86400
但是后者正在被破坏,因为 s 是未知的——当然它是未知的。那么如何将其放入另一个 SELECT 中呢?我需要每个时间戳的最大值,因为每辆车都有自己的最后一次速度测量值,应该回溯 24 小时并计算平均值。希望这能让它更清楚。
假设表名是
Table
。由于您问题中的标签,还假设这是一个 MySQL 数据库。
首先让我们创建一个 CTE,在其中创建一个新列,使用 MySQL 函数 FROM_UNIXTIME()
将 UNIX 时间戳转换为标准时间戳WITH processed AS (
SELECT name, speed, FROM_UNIXTIME(timestamp) AS report_timestamp
FROM Table
)
现在,由于我们拥有所需格式的数据(包括时间戳),让我们来解决问题。我们可以使用窗口函数来做到这一点。
尽管这里需要注意的是,将为每行数据计算平均速度。
为此,根据您的问题,我们将根据当前行的可用时间戳计算每辆车过去 24 小时的平均速度。为此,我们将使用
RANGE
子句来指定 框架定义,在本例中为前 1 天。
我们使用上面的CTE作为源表。
SELECT
*,
AVG(speed) OVER(
PARTITION BY name
ORDER BY report_timestamp ASC
RANGE BETWEEN INTERVAL 1 DAY AND CURRENT ROW
) AS avg_speed_24h
FROM processed;