我在MySQL数据库中有一个表,我想从中选择与另一个给定时间戳具有最接近时间戳的行。
time
是时间戳列(整数UNIX时间戳)。我任意选择了1250710000
。
这是我提出的查询,我想知道是否有更有效的方法:
SELECT *, ABS(time - 1250710000) AS time_dist FROM table
ORDER BY time_dist ASC LIMIT 1
这是最好的方法吗?
答案 0 :(得分:10)
假设time
被编入索引,您几乎可以免费获得 next 记录:
SELECT * FROM table WHERE time > 1250710000 ORDER BY time LIMIT 1
如果我没错,同样适用于前一条记录,MySQL只会以相反的顺序读取索引。使用两者中的UNION,按日期差异命令它们瞧!结果将如下所示
SELECT *
FROM
(
(SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time > 1250710000 ORDER BY time ASC LIMIT 1)
UNION ALL
(SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time < 1250710000 ORDER BY time DESC LIMIT 1)
) AS tmp
ORDER BY time_diff
LIMIT 1
理想情况下,您应使用>
和<
而不是>=
和<=
,并使用其主要ID排除参考记录,以便考虑共享相同时间戳的记录
答案 1 :(得分:1)
正如埃文所说,你拥有它的方式很好。我建议在该时间戳字段上建立索引,以便MySQL可以扫描较小的索引而不是整个表。此外,我会尝试一些'拳击'来看看索引是否可以加快速度:
SELECT *, ABS(time - 1250710000) AS time_dist FROM table
WHERE time between(1250610000,1250810000)
ORDER BY time_dist ASC LIMIT 1
以上限制查询到大约+/- 1天。您必须执行一些基准测试,以查看附加索引扫描(where子句)是否比计算表中所有条目的ABS()更快。
答案 2 :(得分:1)
选择较大和最大的最小时间会更有效 时间小于那两个人的绝对时间。这应该避免不得不操作 整个桌子。
SELECT MAX(时间)AS prev WHERE time&lt; 1250710000;
SELECT MIN(time)AS next WHERE time&gt; 1250710000;
SELECT MIN(ABS(上一个),ABS(下一个));
我的SQL不够强大,无法将这些组合成一个,以及三个的开销 查询可能会扼杀任何节省,但也许有可能。