After reading this, I think you can use the Haversine formula to calculate the distance between two points, given the latitude and longitude of each one:
Here's an example:
select zc.*
-- First, convert the latitude and longitude to radians:
, @lat1 := radians(@latitude) as lat1_rad
, @lon1 := radians(@longitude) as lon1_rad
, @lat2 := radians(zc.latitude) as lat2_rad
, @lon2 := radians(zc.longitude) as lon2_rad
-- Calculate the differences in latitude and longitude:
, @delta_lat := @lat2 - @lat1 as delta_lat
, @delta_lon := @lon2 - @lon1 as delta_lon
-- The Haversine Formula:
, @a := pow(sin(@delta_lat / 2), 2) + cos(@lat2) * cos(@lat1) * pow(sin(@delta_lon / 2), 2) as a
, @c := 2 * atan2(sqrt(@a), sqrt(1 - @a)) as c
, @d := @R * @c as d -- Distance (Km)
from
(select @R := 6371 -- The radius of the earth (Km)
, @latitude := 65.3234 -- Latitude of the initial point
, @longitude := -78.3232 -- Longitude of the initial point
) as init,
zip_codes as zc
-- Add any WHERE conditions and/or ORDER
;
If you want to put this in a function:
delimiter $$
create function haversine_distance(latitude1 double, longitude1 double
, latitude2 double, longitude2 double)
returns double
-- Input: Latitude and longitude of the points you want to calculate,
given in degrees
begin
declare lat1, lon1, lat2, lon2 double;
declare delta_lat, delta_lon double;
declare a, c, d double;
declare R double default 6371; -- The radius of the Earth
-- Convert the inputs to radians
set lat1 = radians(latitude1);
set lon1 = radians(longitude1);
set lat2 = radians(latitude2);
set lon2 = radians(longitude2);
-- Calculate the differences between latitudes and longitudes
set delta_lat = lat2 - lat1;
set delta_lon = lon2 - lon1;
-- The Haversine formula
set a = pow(sin(@delta_lat / 2), 2) +
cos(lat2) * cos(lat1) * pow(sin(delta_lon / 2), 2);
set c = 2 * atan2(sqrt(a), sqrt(1 - 1);
set d = R * c;
return d;
end $$
delimiter ;
And finally, you can use this function to calculate the distances between two points, and filter the nearest n
. I'll use user variables to define the latitude and longitude of the origin point:
set @latitude1 = 65.3234, @longitude1 = -78.3232;
set @n = 5; -- The number of nearest points
select zc.*
, haversine_distance(@latitude1, @longitude1,
zc.latitude, zc.longitude) as distance_km
from zip_codes as zc
order by distance_km
limit @n;