2009-05-23 89 views
2

可以说我有一个表格,其中包含一个充满记录的时间戳列,我想用一个查询来计算两个连续记录之间的最小时间差。如何计算连续事件之间的最短时间?

也许表像...

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

回答

3

假设在第E时间戳记(以防止出现在同一时间在两个录音):

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

这回答了问题,而恰恰 - 并没有传达其它有用信息(如这两个时间戳或温度)。在支持子查询以及分贝---

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 
+0

正常工作需要在MySQL年龄约10,000行:( 对`diff`产生奇怪的值进行测试,如-20090500997993 – araqnid 2009-05-23 13:11:53

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 

第一个加入寻求所有以前的行为当前(“当前”)行。第二个连接在第一行和第二行之间寻找行。 where语句表示在第一行和第二行之间不能有任何行。这样,你就可以得到一行行的列表。

+0

这将活像,但会很慢,并且不能正确处理重复时间戳 – Quassnoi 2009-05-23 17:03:14

+0

您是否需要将MIN()函数应用于时间差和相应的GROUP BY子句?您不需要检查是否存在间隔因为如果有的话,第一个和第二个之间的时间差会小于第一个和第三个之间的时间差,因此MIN()会摆脱它。在其他情况下,您必须确保没有中间读数在当前和以前之间,并且这使事情变得复杂化无法结束。 – 2009-05-23 17:05:10

+0

@Jonathan:有一个加入与INBETWEEN这个检查。 – Quassnoi 2009-05-23 17:16:35

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由于bug 20111

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

根据当前记录的id,可以通过创建返回先前温度的UDF解决此问题。

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

如果你不使用任何过滤条件,则它使用会话变量的解决方案将是最有效的,但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,这将工作OK,只要你有(timestamp, id)指数(或只是(timestamp),如果你的PRIMARY KEY被聚集)