Имате доста добра справка там за mySQL търсене от разстояние.
Забравете за нещата на Oracle Spatial. Твърде много код, твърде много сложност, недостатъчна добавена стойност.
Ето една заявка, която ще свърши работа. Това използва разстояния в статутни мили. РЕДАКТИРАНЕ Това коригира грешката, спомената от mdarwin, с цената на проверка на разделяне, ако се опитате да го използвате за местоположение на северния или южния полюс.
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
Ако работите в километри, променете mydst/69 на mydst/111.045 и променете 3959 на 6371.4. (1/69 преобразува мили в градуси; 3959 е стойност за радиуса на планетата.)
Сега вероятно ще се изкушите да използвате тази голяма заявка като „магическа черна кутия“. Не го прави! Не е много трудно за разбиране и ако го разберете, ще можете да вършите по-добра работа. Ето какво се случва.
Тази клауза е сърцето на това, което прави заявката бърза. Той търси в таблицата ви с градове градове в близост до точката, която сте посочили.
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))))
За да работи, определено се нуждаете от индекс във вашата колона LATITUDE. Индекс във вашата колона LONGITUDE също ще помогне малко. Той прави приблизително търсене, като търси редове, които са в рамките на квази-правоъгълен участък на повърхността на земята близо до вашата точка. Той избира твърде много градове, но не твърде много.
Тази клауза тук ви позволява да елиминирате допълнителните градове от вашия набор от резултати:
WHERE distance <= mydst
Тази клауза е формулата за хаверсинус, която изчислява разстоянието по големия кръг между всеки град и вашата точка.
<предварителен (3959 * ACOS(COS(RADIANS(LATITUDE))
* COS(RADIANS(mylat))
* COS(RADIANS(LONGITUDE) - RADIANS(mylng))
+ SIN(RADIANS(LATITUDE))
* SIN(RADIANS(mylat))
Тази клауза ви позволява да въведете вашата точка и вашата граница на радиуса само веднъж като обвързани променливи към вашата заявка. Полезно е, защото различните формули използват тези променливи многократно.
SELECT :LAT AS mylat,
:LONG AS mylng,
:RADIUS_LIMIT AS mydst
FROM DUAL
Останалата част от заявката просто организира нещата, така че да избирате и подреждате по разстояние.
Ето по-пълно обяснение:http://www.plumislandmedia.net /mysql/haversine-mysql-nearest-loc/