2009-08-20 106 views
6

我在MySQL数据库中有一张表,我想从中选择最接近另一个给定时间戳的时间戳。找到MySQL中最接近的整数的最有效方法?

time是时间戳列(整数UNIX时间戳)。我随意选择1250710000

这是我想出来的查询,我想知道是否有一个更有效的方式做到这一点:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
ORDER BY time_dist ASC LIMIT 1 

这是做的最好的方法是什么?

回答

10

假设time被索引,你可以得到下一个记录几乎免费:

SELECT * FROM table WHERE time > 1250710000 ORDER BY time LIMIT 1 

如果我没有错,同样应适用于以前的记录,MySQL将刚刚读索引以相反的顺序。使用两者的联合,通过日期差异和瞧!其结果将是这样

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排除参考记录,考虑到记录共享相同的时间戳。

+0

该死!我只是打字几乎完全一样! – NickZoic 2009-08-20 04:06:25

+0

好主意,但参考时间戳(本例中为'1250710000')不在同一个表中。 说了这么多,我认为这个查询在效率方面大致相同? – heyitsme 2009-08-20 06:43:29

+0

** @ cyouung:**这个查询在效率方面不尽相同。你的查询在每一行上都有一个ABS(时间 - 125071000)*。只要你有'时间'的索引,这个查询永远不会读取两行以上的数据。 – 2009-08-20 07:32:49

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()更快。

+0

我不喜欢这样的任意限制。 – 2009-08-20 07:29:46

1

选择最小时间大一些,最大时间小于那么两个abs会更有效率吗?这应该避免必须在整个表格上操作 。

SELECT MAX(time)AS prev WHERE time < 1250710000;

SELECT MIN(time)AS next WHERE time> 1250710000;选择MIN(ABS(prev),ABS(next));

我的SQL不够强大,无法将它们合并为一个,并且三个 查询的开销可能会导致任何节省,但这可能是可能的。

相关问题