2012-01-16 48 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