Acho que sua pergunta diz que você tem a
city
valores para as duas cidades entre as quais você deseja calcular a distância. Esta consulta fará o trabalho para você, fornecendo a distância em km. Ele usa a fórmula da lei do cosseno esférico.
Observe que você une a tabela a ela mesma para poder recuperar dois pares de coordenadas para o cálculo.
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
Observe que a constante
111.1111
é o número de quilômetros por grau de latitude, baseado na antiga definição napoleônica do metro como um décimo de milésimo da distância do equador ao pólo. Essa definição é próxima o suficiente para o trabalho de localização. Se você quiser milhas terrestres em vez de quilômetros, use
69.0
em vez de. http://sqlfiddle.com/#!9/21e06/412/0
Se você estiver procurando por pontos próximos, pode ficar tentado a usar uma cláusula mais ou menos assim:
HAVING distance_in_km < 10.0 /* slow ! */
ORDER BY distance_in_km DESC
Isso é (como dizemos perto de Boston MA USA) muito lento.
Nesse caso, você precisa usar um cálculo de caixa delimitadora. Veja este artigo sobre como fazer isso. http://www.plumislandmedia.net/mysql/haversine-mysql- local-proximo/
A fórmula contém um
LEAST()
função. Por quê? Porque o ACOS()
a função lança um erro se seu argumento for um pouco maior que 1. Quando os dois pontos em questão estiverem muito próximos, a expressão com o COS()
e SIN()
os cálculos às vezes podem gerar um valor ligeiramente maior que 1 devido a floating-point epsilon (imprecisão
). A LEAST(1.0, dirty-great-expression)
chamada lida com esse problema. Existe uma maneira melhor, uma fórmula por Thaddeus Vincenty . Ele usa
ATAN2()
em vez de ACOS()
por isso é menos suscetível a problemas de epsilon.