2013-08-16 81 views
2

我有一个与datestamps事件表,我想显示事件之间的时间间隔。举例来说,如果我有计算记录之间的时间?

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 

最后一列的格式并不重要 - 它可以是毫秒,秒,东西人类可读,无论简单。另外请注意,实际的数据有适当的日期,我只是懒得输入日期。

重要的是,在记录中没有指向“a”作为前一个事件的“b”,所以像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个记录,所以一定出事了。

+1

你选择10条记录,但内部查询有做计算你的百万+的记录。 – ApplePie

+0

如果你想要你的最后10条记录是不可能通过时间戳限制你的内部查询到最后10条记录? – Prix

+0

人。给定一条记录,我知道如何编写一个查询,用于“选择日期戳记的最小值小于myrecord.datestamp”的记录,并且该查询将立即返回。我想我需要以某种方式“嵌套”,而不是? – Coderer

回答

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

前2列有点多余,但否则应该起作用。 – Vatev

+0

此解决方案快速有效,但我不确定如何更改它以查看最近的事件而不是最旧的事件。请注意,我有一百万个事件,而且我主要关心最近的事件。 – Coderer

+0

@Coderer我已经添加了一个查询来选择最近的记录。 – valex

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

+0

巧妙地使用嵌套选择来隐藏来自变量赋值的多余值。您也可以从选择中删除'event'和'datestamp',并用'(@PrevDate:= datestamp)AS datestamp'替换'@PrevDate:= datestamp'等。列的顺序是错误的,真的不重要。 – Coderer

相关问题