计算记录之间的时间?

时间:2013-08-16 11:48:24

标签: mysql sql

我有一个带有日期戳的事件表,我想显示事件之间的时间间隔。例如,如果我有

event  |  datestamp
-------------------
  a    |   05:00
  b    |   07:00
  c    |   08:00
  d    |   12:00
 ...

我想写一个简单的查询给我

event  |  datestamp  |  last | since_last
-----------------------------------------
  a    |   05:00     |  NULL |  NULL
  b    |   07:00     |   a   |  2 hours
  c    |   08:00     |   b   |  1 hour
  d    |   12:00     |   c   |  4 hours

最后一列的格式并不重要 - 它可以是毫秒,秒,人类可读的东西,无论多么容易。另请注意,实际数据具有正确的日期时间,我只是懒得键入日期。

重要的是,“b”记录中没有任何内容指向“a”作为前一个事件,因此像in this question这样的解决方案不起作用 - 我需要一些语法选择加入最新旧记录的所有记录。

我尝试过的似乎是

SELECT new.event, new.datestamp, old.event AS last,
    TIMESTAMPDIFF(SECOND, MAX(old.datestamp), new.datestamp) AS since_last
FROM events AS new, events AS old
WHERE new.datestamp > old.datestamp
LIMIT 10;

但它似乎只是挂起 - 我让它运行超过一分钟。每this question,我试过

SELECT event, datestamp,
  (SELECT MAX(old.datestamp)
   FROM events old
   WHERE new.datestamp > old.datestamp
  ) last_ds
FROM events new
LIMIT 10;

这实际上有效,但在我的桌子上有超过14秒的事件,有一百万个事件,即使我只选择了10条记录,所以一定有些错误。

2 个答案:

答案 0 :(得分:3)

尝试使用

select event,datestamp,
       @PrevEvent as last,  
       TIMESTAMPDIFF(SECOND, @PrevDate, datestamp) AS since_last,
       @PrevDate:=datestamp,
       @PrevEvent:=event
from events, (select @PrevDate:=null,@PrevEvent:=null) t
order by datestamp

SQLFiddle demo

要选择最近10个事件,只需使用带LIMIT的子查询而不只是events表。

select event,datestamp,
       @PrevEvent as last,  
       TIMESTAMPDIFF(SECOND, @PrevDate, datestamp) AS since_last,
       @PrevDate:=datestamp,
       @PrevEvent:=event
from ( select *
       from events
       order by datestamp DESC
       LIMIT 10
     ) t1, (select @PrevDate:=null,@PrevEvent:=null) t
order by datestamp

UPD:

要在最近的10个中获得正确的第一行(不是NULL since_last字段),首先应该在内部子查询中使用LIMIT 11(10 + 1),然后在外部查询LIMIT 10 OFFSET 1中。

select event,datestamp,last,since_last
FROM
(
select event,datestamp,
       @PrevEvent as last,  
       TIMESTAMPDIFF(SECOND, @PrevDate, datestamp) AS since_last,
       @PrevDate:=datestamp,
       @PrevEvent:=event
from ( select *
       from events
       order by datestamp DESC
       LIMIT 11
     ) t1, (select @PrevDate:=null,@PrevEvent:=null) t
order by datestamp
) t3 
LIMIT 10 offset 1

答案 1 :(得分:1)

Select event,datestamp,last,since_last FROM
(select event,datestamp,
       @PrevEvent as last,  
       concat((TIMESTAMPDIFF(SECOND, @PrevDate, datestamp))/3600,
              ' Hours') AS since_last,
       @PrevDate:=datestamp,
       @PrevEvent:=event
from events, (select @PrevDate:=null,@PrevEvent:=null) t
order by datestamp) abc

<强> Fiddle