2012-01-16 87 views
0

好吧,我正在建立一个外卖取景器,它将在设定的英国邮政编码范围内找到外卖。用户将他/她的邮编放在输入框中并点击提交,网站就会在用户附近搜索外卖。但问题在于,这种搜索是基于个人外卖交货距离。因此,如果外卖店的送货距离为12英里,而人员邮政编码在外卖店12英里内,则会在结果中显示。外卖餐厅查找帮助在php

到目前为止,我有英国邮政编码数据库与朗和纬度坐标,也外卖数据库表持有外卖自己的邮政编码和其交付距离,但不是外卖邮递区的长和纬度值。

我所要求的并不是代码,而是如何做到这一点的逻辑帮助。

我有以下查询,将找到一个给定的长,纬度,但林不知道一套半径范围内的所有邮政编码如果在英里,如果它是最快的则可能是:

SELECT * , 6371 * ACos(Cos(RADIANS(latitude)) * Cos(RADIANS(56.0062)) * Cos(  RADIANS(- 3.78189) - RADIANS(longitude)) + Sin(RADIANS(latitude)) * Sin(RADIANS(56.0062))) AS Distance 
FROM postcodes 
HAVING Distance <= '10' 
ORDER BY Distance 
LIMIT 3720 , 30 
+0

它以公里为单位。改变'6371'到'3963.1676'获得里程。 (这是地球的半径。) – 2012-01-16 23:56:18

+0

谢谢,那就清除一个问题。 – user794846 2012-01-17 00:05:00

回答

0

对于性能,考虑消除你不需要的领域。问题是你正在对计算值进行排序,因此每行都需要检查。

理想情况下,您将执行额外的筛选以减少所需的行数。也许匹配邮政编码的前缀可能会有所帮助。你可能会发现,如果邮政编码的前X个字符不匹配,那么它必须超过12英里。

如果您有很多字段需要检索,您还可以从late row lookup看到一个很大的性能提升。在你的情况下,这是特别有用的,因为你可以提供一个更小的数据集供MySQL进行排序。

这个想法只会拉每个记录的ID和距离,对它们进行排序,然后拉出前N个记录(无论你需要多少记录)。然后,您可以使用您提取的ID返回原始表并检索其余数据。这很有帮助,因为它允许MySQL在执行排序时使用较少的内存,并且如果数据集不在内存中,则可能会避免某些磁盘查找,具体取决于行的大小。

+0

另一种方法是计算边界框,并在SELECT语句的WHERE子句中使用这些值,因此仅对数据的子集执行昂贵的计算 – 2012-01-17 00:38:07

+0

True。虽然边界框对于lat/long很棘手,因为它具有固定的度数值,但当您改变与极点的距离时,框的物理尺寸将会发生显着变化。 – 2012-01-17 00:52:24

+0

我认为在这种情况下,最大距离是不知道的,直到外带记录被读取并且它们的最大免费递送被检索到,这使得很难在HAVING子句中使用 – 2012-01-17 00:54:58

0

另一个完全独立的选项。如果你只关注英国,你可以考虑在笛卡尔坐标系中使用某种类型的投影。我相信OSGB可能适合英国,并应该给最小的错误。

这样可以使用MySQL的spatial extensions在一系列点列上添加一个R-tree索引。这并不能为您提供足够的距离,但它可以使您将数据集缩小到可以有效计算真实距离的较小部分。

+0

我几乎不知道如何去做像这样的事情大声笑 – user794846 2012-01-17 09:23:10

+0

你是否只专注于英国?这将决定这种方法是否有意义。 – 2012-01-17 12:21:36

+0

您可能会认为[geohashing](http://en.wikipedia.org/wiki/Geohash)可能更容易实施。在geohash上做前缀匹配可以高效地索引。 – 2012-01-17 15:18:17