Du har en ganska bra referens där för mySQL-distanssökning.
Glöm Oracle Spatial-grejer. För mycket kod, för mycket komplexitet, inte tillräckligt med mervärde.
Här är en fråga som kommer att göra susen. Detta använder avstånd i lagstadgade miles. REDIGERA Detta åtgärdar felet som nämns av mdarwin, till priset av delningskontroll om du försöker använda det för en plats vid nord- eller sydpolen.
SELECT id, city, LATITUDE, LONGITUDE, distance
FROM
(
SELECT id,
city,
LATITUDE, LONGITUDE,
(3959 * ACOS(COS(RADIANS(LATITUDE))
* COS(RADIANS(mylat))
* COS(RADIANS(LONGITUDE) - RADIANS(mylng))
+ SIN(RADIANS(LATITUDE))
* SIN(RADIANS(mylat))
))
AS distance,
b.mydst
FROM Cities
JOIN (
SELECT :LAT AS mylat,
:LONG AS mylng,
:RADIUS_LIMIT AS mydst
FROM DUAL
)b ON (1 = 1)
WHERE LATITUDE >= mylat -(mydst/69)
AND LATITUDE <= mylat +(mydst/69)
AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
)a
WHERE distance <= mydst
ORDER BY distance
Om du arbetar i kilometer, ändra mydst/69 till mydst/111.045 och ändra 3959 till 6371.4. (1/69 konverterar miles till grader; 3959 är ett värde för planetens radie.)
Nu kommer du förmodligen att bli frestad att använda den här stora frågan som en "magisk svart låda". Gör det inte! Det är inte särskilt svårt att förstå, och om du förstår det kommer du att kunna göra ett bättre jobb. Här är vad som händer.
Denna klausul är hjärtat i det som gör frågan snabb. Den söker i din stadstabell efter närliggande städer till den punkt du angav.
WHERE LATITUDE >= mylat -(mydst/69)
AND LATITUDE <= mylat +(mydst/69)
AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
För att det ska fungera behöver du definitivt ett index på din LATITUDE-kolumn. Ett index på din LONGITUDE-kolumn hjälper också lite. Den gör en ungefärlig sökning, letar efter rader som är inom en kvasi-rektangulär fläck på jordens yta nära din punkt. Den väljer ut för många städer, men inte alldeles för många.
Denna klausul här låter dig eliminera de extra städerna från din resultatuppsättning:
WHERE distance <= mydst
Den här klausulen är haversinformeln som beräknar avståndet i storcirkeln mellan varje stad och din punkt.
(3959 * ACOS(COS(RADIANS(LATITUDE))
* COS(RADIANS(mylat))
* COS(RADIANS(LONGITUDE) - RADIANS(mylng))
+ SIN(RADIANS(LATITUDE))
* SIN(RADIANS(mylat))
Den här klausulen låter dig ange din punkt och din radiegräns bara en gång som bundna variabler till din fråga. Det är användbart eftersom de olika formlerna använder dessa variabler flera gånger.
SELECT :LAT AS mylat,
:LONG AS mylng,
:RADIUS_LIMIT AS mydst
FROM DUAL
Resten av frågan organiserar helt enkelt saker så att du väljer och beställer efter avstånd.
Här är en mer fullständig förklaring:http://www.plumislandmedia.net /mysql/haversine-mysql-nearest-loc/