如何计算连续事件之间的最小时间段?

时间:2009-05-23 08:40:26

标签: sql mysql timestamp

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

也许像......这样的表。

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

4 个答案:

答案 0 :(得分: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

由于bug 20111,此解决方案在MySQL中的效率非常低。

子查询不会使用range访问路径,但它会使用(timestampid)上的索引进行排序。

考虑到当前记录的UDF,可以通过创建返回先前温度的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已群集),这将正常运行

答案 1 :(得分:3)

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

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

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

答案 2 :(得分: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语句表示第一行和第二行之间不能有任何行。这样,您将得到一个包含前一行的行列表。

答案 3 :(得分: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