Myślę, że twoje pytanie mówi, że masz city
wartości dla dwóch miast, między którymi chcesz obliczyć odległość.
To zapytanie wykona zadanie za Ciebie, podając odległość w km. Wykorzystuje wzór sferycznego cosinusa.
Zauważ, że łączysz tabelę ze sobą, dzięki czemu możesz pobrać dwie pary współrzędnych do obliczeń.
SELECT a.city AS from_city, b.city AS to_city,
111.111 *
DEGREES(ACOS(LEAST(1.0, COS(RADIANS(a.Latitude))
* COS(RADIANS(b.Latitude))
* COS(RADIANS(a.Longitude - b.Longitude))
+ SIN(RADIANS(a.Latitude))
* SIN(RADIANS(b.Latitude))))) AS distance_in_km
FROM city AS a
JOIN city AS b ON a.id <> b.id
WHERE a.city = 3 AND b.city = 7
Zauważ, że stała 111.1111
to liczba kilometrów na stopień szerokości geograficznej, oparta na starej napoleońskiej definicji metra jako jednej dziesięciotysięcznej odległości od równika do bieguna. Ta definicja jest wystarczająco zbliżona do pracy z lokalizatorem.
Jeśli chcesz otrzymać mile ustawowe zamiast kilometrów, użyj 69.0
zamiast tego.
http://sqlfiddle.com/#!9/21e06/412/0
Jeśli szukasz punktów w pobliżu, możesz pokusić się o użycie klauzuli podobnej do tej:
HAVING distance_in_km < 10.0 /* slow ! */
ORDER BY distance_in_km DESC
To jest (jak mówimy w pobliżu Boston MA USA) nikczemnie powolne.
W takim przypadku musisz użyć obliczenia obwiedni. Zobacz ten zapis o tym, jak to zrobić. http://www.plumislandmedia.net/mysql/haversine-mysql- najbliższy-loc/
Formuła zawiera LEAST()
funkcjonować. Czemu? Ponieważ ACOS()
funkcja wyrzuca błąd, jeśli jej argument jest nawet nieco większy niż 1. Gdy te dwa punkty są bardzo blisko siebie, wyrażenie z COS()
i SIN()
obliczenia mogą czasami dać wartość nieco większą niż 1 z powodu zmiennoprzecinkowej epsilon (niedokładność
). LEAST(1.0, dirty-great-expression)
telefon radzi sobie z tym problemem.
Jest lepszy sposób, wzór
autor:Thaddeus Vincenty
. Używa ATAN2()
zamiast ACOS()
więc jest mniej podatny na problemy z epsilon.