Du har en ret god reference der til mySQL-afstandssøgning.
Glem alt om Oracle Spatial-tingene. For meget kode, for meget kompleksitet, ikke nok værditilvækst.
Her er en forespørgsel, der vil gøre tricket. Dette bruger afstande i statut miles. REDIGER Dette retter fejlen nævnt af mdarwin, på bekostning af divide-checking, hvis du prøver at bruge den til en placering på 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
Hvis du arbejder i kilometer, skal du ændre mydst/69 til mydst/111.045 og ændre 3959 til 6371.4. (1/69 konverterer miles til grader; 3959 er en værdi for planetens radius.)
Nu vil du sandsynligvis blive fristet til at bruge denne store forespørgsel som en "magisk sort boks." Gør det ikke! Det er ikke særlig svært at forstå, og hvis du forstår det, vil du være i stand til at gøre et bedre stykke arbejde. Her er, hvad der sker.
Denne klausul er kernen i det, der gør forespørgslen hurtig. Den søger i tabellen Byer for nærliggende byer til det punkt, du har angivet.
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))))
For at det kan fungere, skal du helt sikkert have et indeks på din LATITUDE-kolonne. Et indeks på din LONGITUDE kolonne vil også hjælpe lidt. Den udfører en omtrentlig søgning og leder efter rækker, der er inden for en kvasi-rektangulær plet på jordens overflade nær dit punkt. Den udvælger for mange byer, men ikke alt for mange.
Denne klausul her lader dig fjerne de ekstra byer fra dit resultatsæt:
WHERE distance <= mydst
Denne klausul er haversineformlen, som beregner afstanden mellem storcirklerne mellem hver by og dit punkt.
(3959 * ACOS(COS(RADIANS(LATITUDE))
* COS(RADIANS(mylat))
* COS(RADIANS(LONGITUDE) - RADIANS(mylng))
+ SIN(RADIANS(LATITUDE))
* SIN(RADIANS(mylat))
Denne klausul lader dig indtaste dit punkt og din radius-grænse én gang som bundne variabler til din forespørgsel. Det er nyttigt, fordi de forskellige formler bruger disse variable flere gange.
SELECT :LAT AS mylat,
:LONG AS mylng,
:RADIUS_LIMIT AS mydst
FROM DUAL
Resten af forespørgslen organiserer simpelthen tingene, så du vælger og bestiller efter afstand.
Her er en mere komplet forklaring:http://www.plumislandmedia.net /mysql/haversine-mysql-nearest-loc/