Myslím, že vaše otázka říká, že máte city
hodnoty pro dvě města, mezi kterými chcete vypočítat vzdálenost.
Tento dotaz udělá práci za vás a poskytne vzdálenost v km. Používá vzorec sférického kosinusového zákona.
Všimněte si, že připojíte tabulku k sobě, takže můžete získat dva páry souřadnic pro výpočet.
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
Všimněte si, že konstanta 111.1111
je počet kilometrů na stupeň zeměpisné šířky, založený na staré napoleonské definici metru jako jedné desetitisíciny vzdálenosti od rovníku k pólu. Tato definice je dostatečně blízká pro práci s hledáním polohy.
Pokud chcete míle podle zákona místo kilometrů, použijte 69.0
místo toho.
http://sqlfiddle.com/#!9/21e06/412/0
Pokud hledáte body v okolí, můžete být v pokušení použít klauzuli přibližně jako toto:
HAVING distance_in_km < 10.0 /* slow ! */
ORDER BY distance_in_km DESC
To je (jak říkáme poblíž Boston MA USA) strašně pomalé.
V takovém případě musíte použít výpočet hraničního rámečku. Podívejte se na tento zápis o tom, jak to udělat. http://www.plumislandmedia.net/mysql/haversine-mysql- nejbližší-loc/
Vzorec obsahuje LEAST()
funkce. Proč? Protože ACOS()
funkce vyvolá chybu, pokud je její argument byť jen o něco větší než 1. Když jsou dva příslušné body velmi blízko u sebe, výraz s COS()
a SIN()
výpočty mohou někdy poskytnout hodnotu mírně vyšší než 1 kvůli epsilon s plovoucí desetinnou čárkou (nepřesnost
). LEAST(1.0, dirty-great-expression)
volání se s tímto problémem vyrovná.
Existuje lepší způsob, vzorec
od Thaddeus Vincenty
. Používá ATAN2()
spíše než ACOS()
takže je méně náchylný k problémům epsilon.