Problema
Nós usualmente temos que listar lojas mais perto de um CEP e exibir a distância entre dois pontos tambem.
Solução
A solução está dentro do próprio SQL (MSSQL neste caso, mas provavelmente pode ser facilmente modificada para outro database).
Explicação detalhada
Para calcular a distância entre dois pontos (par de latitude/longitude) na superfície da Terra, temos que usar a lei dos cosenos (Spherical Law of Cosines) mostrada abaixo:
d = acos( sin(φ1).sin(φ2) + cos(φ1).cos(φ2).cos(Δλ) ).R
onde: φ = latitude, λ = longitude, R = raio da Terra, d = distância entre dois pontos
e a fórmula para calcular a distância usando uma query SQL em ColdFusion é mostrada abaixo:
Isto requer que voce passe a latitude/longitude para os locais que voce estiver pesquisando e assume que voce tenha os valores latitude/longitude para uma loja armazenados em um database. (Ou voce pode join com uma tabela de CEPs para obter os pares de latitude/longitude).
O valor 69.17073 e usado para converter a distância em milhas e o valor 111.3195 e usado para converter a distância em quilômetros. Este valor é mais exato para os pontos perto do equador e varia quando se desvia da linha equatorial.
<!--- km ---> <!--- mi ---> <!--- distance from the point you are searching for ---> <!--- degrees - tweak according to your needs / it should be related to the distance you set above this will help limit the records searched instead of having to perform the calculation for every record ---> <!--- pass in this value ---> <!--- pass in this value ---> Select #radius# * Degrees( acos( sin(radians(#latitude#))*sin(radians(store.latitude)) + cos(radians(#latitude#)) * cos(radians(store.latitude)) * cos(radians(store.longitude)-radians(#longitude#)) ) ) As distance, store.name From store Where ( store.latitude between #latitude# - #searchDegree# and #latitude# + #searchDegree# ) And ( store.longitude between #longitude# - #searchDegree# and #longitude# + #searchDegree# ) And ( #radius# * Degrees( acos( sin(radians(#latitude#))*sin(radians(store.latitude)) + cos(radians(#latitude#)) * cos(radians(store.latitude)) * cos(radians(store.longitude)-radians(#longitude#)) ) ) ) < #distance# Order By distance, name