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;