场景
你有一个包含记录的表,每条记录都有一个 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:那问题是什么?
此解决方案适用于小表,但由于显而易见的原因,对于长表扫描效率不高,如何改进此查询以有效地获得相同的结果?请注意,时间戳
已编入索引。
最佳答案
最快的方法可能是使用变量。我倾向于这样表述:
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/