方案
您有一个包含记录的表,每个记录都有一个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
已编入索引。
答案 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