2

假设我有一个包含记录的时间戳列的表,我想仅使用一个查询来计算两个连续记录之间的最小时间差。

也许像一张桌子......

CREATE TABLE `temperatures` (
  `temperature` double,
  `time` timestamp DEFAULT CURRENT_TIMESTAMP
);
4

4 回答 4

4

您需要的是分析函数LAGMIN.

它们在 中缺失MySQL,但可以使用会话变量轻松模拟。

此查询返回连续记录之间的所有差异:

SELECT  (temperature - @r) AS diff,
        @r := temperature
FROM    (
        SELECT  @r := 0
        ) vars,
        temperatures
ORDER BY
        time

这个返回最小的时间差:

SELECT  (
        SELECT  id,
                @m := LEAST(@m, TIMEDIFF(time, @r)) AS mindiff,
                @r := time
        FROM    (
                SELECT  @m := INTERVAL 100 YEAR,
                        @r := NULL
                ) vars,
                temperatures
        ORDER BY
                time, id
        ) qo
WHERE   qo.id = 
        (
        SELECT  id
        FROM    temperatures
        ORDER BY
                time DESC, id DESC
        LIMIT 1
        )

请参阅我的博客中的这篇文章,了解如何在以下位置模拟分析函数MySQL

如果您PRIMARY KEY向您的表格添加一个(您应该始终这样做!),那么您可以使用更多SQL-ish 解决方案:

SELECT  temperature -
        (
        SELECT temperature
        FROM   temperatures ti
        WHERE  (ti.timestamp, ti.id) < (to.timestamp, to.id)
        ORDER BY
               ti.timestamp DESC, ti.id DESC
        LIMIT 1
        )
FROM    temperatures to
ORDER BY
       to.timestamp, to.id

但是,MySQL由于存在错误 20111 ,此解决方案效率非常低。

子查询将不使用range访问路径,尽管它将使用 ( timestamp, id) 上的索引进行排序。

这可以通过创建UDF返回先前温度的 a 来解决,给定当前记录的id.

有关详细信息,请参阅我的博客中的这篇文章:

如果您不使用任何过滤条件,那么使用会话变量的解决方案将是最有效的,尽管MySQL具体。

类似的解决方案SQL Server如下所示:

SELECT  temperature -
        (
        SELECT TOP 1 temperature
        FROM   temperatures ti
        WHERE  ti.timestamp < to.timestamp
               OR (ti.timestamp = to.timestamp AND ti.id < to.id)
        ORDER BY
               ti.timestamp DESC, ti.id DESC
        )
FROM    temperatures to
ORDER BY
       to.timestamp, to.id

SELECT  MIN(mindiff)
FROM    (
        SELECT  timestamp -
                (
                SELECT TOP 1 timestamp
                FROM   temperatures ti
                WHERE  ti.timestamp < to.timestamp
                       OR (ti.timestamp = to.timestamp AND ti.id < to.id)
                ORDER BY
                       ti.timestamp DESC, ti.id DESC
                ) AS mindiff
        FROM    temperatures to
        ORDER BY
               to.timestamp, to.id
        ) q

SQL Server中,这可以正常工作,前提是您有一个索引(timestamp, id)(或仅在 上(timestamp),如果您PRIMARY KEY是集群的)

于 2009-05-23T12:24:34.743 回答
3

假设时间戳有唯一约束(防止同时有两个记录):

SELECT MIN(timediff(t1.`time`, t2.`time`)) AS delta_t,
    FROM temperatures t1 JOIN temperatures t2 ON t1.`time` < t2.`time`

这相当准确地回答了问题 - 并且不传达其他有用的信息(例如哪两个时间戳或温度)。

于 2009-05-23T17:10:59.660 回答
2

尝试这样的查询:

select 
    cur.timestamp as CurrentTime,
    prev.timestamp as PreviousTime,
    timediff(cur.timestamp,prev.timestamp) as TimeDifference,
    cur.temperature - prev.temperature as TemperatureDifference
from temperatures cur
left join temperatures prev on prev.timestamp < cur.timestamp
left join temperatures inbetween
    on prev.timestamp < inbetween.timestamp
    and inbetween.timestamp < cur.timestamp
where inbetween.timestamp is null

第一个连接查找当前(“cur”)行的所有先前行。第二个连接查找第一行和第二行之间的行。where 语句表示第一行和第二行之间不能有任何行。这样,您将获得包含前一行的行列表。

于 2009-05-23T08:49:53.303 回答
0

你可以试试这个:

SELECT
    T1.*,
    (SELECT MIN(T2.time)
     FROM temperatures T2
     WHERE T2.time > T1.time)-T1.time diff
FROM
    temperatures T1
ORDER BY
    T1.time
于 2009-05-23T08:48:25.223 回答