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

标签 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:那问题是什么?

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

Fiddle

最佳答案

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

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
                 );

关于mysql - 获取时间戳与前一行明显不同的记录 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21579915/

相关文章:

javascript - 如何为列的每一行设置id

java - 在 Android 上使用 MySQL

php - 错误 : datetime column Incorrect datetime value: ''

php mysql,如何获得总时间?

mysql - 通过内部select的结果过滤MySQL结果集

sql - 无法在输出选择中切换列

mysql - 如何在sql中使用update来放置时间戳

java - 定期从 PostgreSQL 获取数据并发送到 ActiveMQ

c++ - Qt 中 PostgreSQL 和 MySQL 的优缺点?

sql - 如何从 select 语句中获取值到变量中?