获取时间戳与前一行明显不同的记录ID

时间:2014-02-05 14:24:58

标签: mysql sql select

方案

您有一个包含记录的表,每个记录都有一个Unix时间戳字段。表结构可以是

CREATE  TABLE `record` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `timestamp` INT NOT NULL ,
 PRIMARY KEY (`id`)
 );

情况:

服务器由于任何原因而关闭,并且记录没有进入,比如让我们说1小时。你去的那天结束时检查表中的记录少于正常记录,你必须检查记录是否在任何时间停止进入。

数据:

id  timestamp   
1   1391607328
2   1391607330
3   1391607332
4   1391607334
5   1391607336
6   1391607353
7   1391607355
8   1391607357
9   1391607359
10  1391607361
11  1391607377
12  1391608378
13  1391608379
14  1391608380
15  1391608381
16  1391608382
17  1391608383
18  1391608384
19  1391608385
20  1391608386

要求:

我们现在必须找出哪个是正常插入的最后一行,之后在插入下一行之前有一个很大的时间间隔。对于这个例子,我们将这个时间间隔量化为1000。 因此,我们检查这20条记录,并注意到我们要查找的行是id=12,因为这是与前一行的时间戳相差大于1000的行。

当前解决方案:

SELECT a.id,a.timestamp 
FROM record a 
WHERE a.timestamp - 1000 >  
   (SELECT MAX(b.timestamp) 
    FROM record b 
    WHERE b.id<a.id
   )

TL; DR:那么问题是什么?

此解决方案适用于小型表,但由于显而易见的原因,它对于长表扫描效率不高,如何改进此查询以有效获得相同的结果?请注意,timestamp已编入索引。

Fiddle

2 个答案:

答案 0 :(得分:1)

最快的方法可能是使用变量。我倾向于这样说:

select id, timestamp, prev_timestamp
from (SELECT id, timestamp, @prevtimestamp as prev_timestamp,
             @prevtimestamp := timestamp
      FROM record r cross join
           (select @prevtimestamp := -1) as const
      order by id
     ) r
where timestamp - prev_timestamp > 1000;

注意:order by应为无操作,因为id是主键。

编辑:

如果您在record(timestamp)上创建索引,则以下内容也会有效:

select r.*
from record r
where not exists (select 1
                  from records r2
                  where r2.timestamp > r.timestamp - 1000 and
                        r2.timestamp < r.timestamp
                 );

答案 1 :(得分:1)

只是抓住你有最大时间跨度差距的id! (假设ID增量为1)

SELECT previous AS TIMESTAMP ,previous_id AS id
FROM
(
  SELECT a.id,b.id AS previous_id ,a.TIMESTAMP,b.TIMESTAMP AS previous,(b.TIMESTAMP - a.TIMESTAMP) AS diff
  FROM record a
   INNER JOIN record b
     ON b.id -1 = a.id
  ORDER BY diff DESC
) AS result_table
LIMIT 1
相关问题