2014-02-22 45 views
0

我試圖完成這個Google tutorial重複記錄的MySQL地理搜索使用交叉聯接和Hversine式

我寫這個SQL使用位置查詢的位置的表的修改「的名字。」鑑於該位置的名稱,該查詢返回鄰近範圍內的比薩餐館。爲了達到這個目的,我加入了我的餐廳位置表,標記爲「標記」,並使用Haversine公式計算距離。

SELECT m.address, 
     m.name, 
     m.lat, 
     m.lng, 
     (3959 * ACOS(COS(RADIANS(poi.lat)) * 
     COS(RADIANS(m.lat)) * 
     COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat))* 
     SIN(RADIANS(m.lat)))) AS distance 
    FROM markers poi 
     CROSS JOIN markers m 
    WHERE poi.address LIKE "%myrtle beach%" 
      AND poi.id <> m.id HAVING distance < 200 
    ORDER BY distance LIMIT 0,20 

該查詢返回預期的結果,但是如果關注點在指定區域之外,在這種情況下,「默特爾海灘,」我知道每場比賽重複的記錄。這是因爲CROSS JOIN會很容易用DISTINCT選擇來修復。但是「lng」和「lat」字段是FLOAT類型,所以即使對於重複記錄,距離計算也不會完全相同。

這裏是回報的一個子集:

3901北國王公路套房1,默特爾海灘,SC |芝加哥東部比薩公司| 33.716099 -78.855583 | 4.0285562196955125

1706 S Kings Hwy#A,Myrtle Beach,SC |多米諾比薩:美特爾海灘| 33.674881 | -78.905144 | 4.0285562196955125

82 Wentworth St,Charleston,SC | Andolinis比薩| 2.782330 | -79.934235 | 85.68177495224947

82 Wentworth St,Charleston,SC | Andolinis比薩| 32.782330 | -79.934235 | 89.71000040441085

114 Jungle Rd,Edisto Island,SC | Edisto Beach Inc的雄鹿披薩| 32.503971 -80.297951 | 114.22243529200529

114 Jungle Rd,Edisto Island,SC | Edisto Beach Inc的雄鹿披薩| 32.503971 -80.297951 | 118.2509427998286"

任何在哪裏何去何從建議

+0

你可以發佈樣品輸入和輸出顯示dups?爲了便於閱讀,我提出了一個假設[Haversine函數存在]的編輯方式(http://stackoverflow.com/questions/6385452/a-custom-mysql-function-to-calculate-the-半正矢-距離)。 – bishop

+0

@Brandon Buster您能否提供您的數據樣本。此外,您的興趣點是什麼意思?我看到的唯一手動輸入的數據是%myrtle beach%。你想做什麼?因爲這個問題有點難以理解,需要澄清和更多細節。 –

+0

對不起,我在幾個不同的情況下使用了「興趣點」一詞。這個例子中的興趣點只有默特爾比奇。我想回來的數據是該點200英里半徑內的披薩餐廳。我會用一些示例數據和更多信息編輯我的帖子 –

回答

1

嘗試:?

select distinct x.address, x.name, y.lat, y.lng, x.distance 
    from (SELECT m.address, 
       m.name, 
       m.lat, 
       m.lng, 
       (3959 * 
       ACOS(COS(RADIANS(poi.lat)) * COS(RADIANS(m.lat)) * 
        COS(RADIANS(m.lng) - RADIANS(poi.lng)) + 
        SIN(RADIANS(poi.lat)) * SIN(RADIANS(m.lat)))) AS distance 
      FROM markers poi 
     cross JOIN markers m 
     WHERE poi.address LIKE "%myrtle beach%" 
      and poi.id <> m.id HAVING distance < 200) x 
    join markers y 
    on x.address = y.address 
    and x.name = y.name 
    and x.lat = y.lat 
    and x.lng = y.lng 
order by x.distance limit 0, 20 
+0

謝謝。指出看起來是一個可行的解決方案。我寧願不執行第三個表連接。如果這是唯一的答案(很可能),我會將其標記爲答案。 –

1

你得到重複的結果,因爲這兩點都符合‘默特爾比奇’使用像poi.id < m.id條件確保你只能得到一個匹配

例:

poi id m id distance 
1   2  100 
2   1  100 

查詢:

SELECT 
    m.address, 
    m.name, 
    m.lat, 
    m.lng, 
    (3959 * ACOS(COS(RADIANS(poi.lat)) * 
    COS(RADIANS(m.lat)) * 
    COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat))* 
    SIN(RADIANS(m.lat)))) AS distance 
FROM markers poi 
CROSS JOIN markers m 
WHERE 
    (poi.address LIKE "%myrtle beach%" OR m.address LIKE "%myrtle beach%") 
    AND poi.id < m.id 
HAVING distance < 200 
ORDER BY distance LIMIT 0,20 

或者,如果你真的這樣做有標記物的興趣點上單排,指定的,而不是對地址的匹配。那麼你的條件poi.id <> m.id將確保沒有重複。

SELECT 
    m.address, 
    m.name, 
    m.lat, 
    m.lng, 
    (3959 * ACOS(COS(RADIANS(poi.lat)) * 
    COS(RADIANS(m.lat)) * 
    COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat))* 
    SIN(RADIANS(m.lat)))) AS distance 
FROM markers poi 
CROSS JOIN markers m 
WHERE 
    poi.id = (SELECT TOP(1) id FROM markers WHERE address LIKE "%myrtle beach%") 
    AND poi.id <> m.id 
HAVING distance < 200 
ORDER BY distance LIMIT 0,20 
+0

感謝您的回覆。它確實消除了重複,儘管它也假設所有匹配記錄的ID都高於我在目標區域中找到的任何記錄,而這些記錄並非總是如此。它給我一個不同的觀點,即我如何編寫SQL。 –

+0

@BrandonBuster,它不會這樣假設,因爲在第一個查詢中,較高或較低編號的行可以匹配。在第二個查詢中,我們不使用'>'比較。 – Mitch

0

回顧大家的回答讓我想到了。與其詢問爲什麼我得到重複結果,我開始想知道哪兩個默特爾比奇位置是計算距離的查詢?答案是兩個。這就解釋了爲什麼我首先得到兩場比賽的紀錄。

這裏是我的解決方案:

SELECT m.address, m.name, m.lat, m.lng, (3959 
    * ACOS(COS(RADIANS(poi.lat)) * COS(RADIANS(m.lat)) 
    * COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat)) 
    * SIN(RADIANS(m.lat))))  AS distance 
FROM markers m 
cross JOIN (
    select name, lat, lng from markers 
    where address like '%myrtle beach %' 
    limit 1 
) poi 
HAVING distance < 200 
ORDER BY name 
LIMIT 0, 20 

這不會給我的最精確的距離計算,因爲它擅自使用了第一家餐廳找到的震中。但爲了我的直接目的,這已經夠好了。我認爲,爲了讓這個應用程序能夠準備好生產,我需要第二個包含城市中心座標的表格。