我有一张满是邮政编码的表格。例如:
------------------------------
| zip | latitude | longitude |
------------------------------
|00001| 35.34543 | -76.34234 |
|00002| 43.23423 | -80.32423 |
...
|00008| 24.34543 | -20.53454 |
------------------------------
对于每一行,我想选择最近的n个邮政编码。但是,我似乎只能弄清楚如何选择最近的单个邮政编码。我如何针对所有邮政编码进行调整:
SELECT
zip, (
3959 * acos (
cos ( radians(78.3232) )
* cos( radians( latitude ) )
* cos( radians( longitude ) - radians(65.3234) )
+ sin ( radians(78.3232) )
* sin( radians( latitude ) )
)
) AS distance
FROM zipcodes
ORDER BY distance
LIMIT 0 , 20;
这将选择20个关闭的邮政编码,但我需要将其应用于每一行。我怎么能一次为整个桌子做这个?
答案 0 :(得分:0)
在阅读this后,我认为你可以使用Haversine公式来计算两点之间的距离,给出每个点的纬度和经度:
以下是一个例子:
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
;
如果你想把它放在一个函数中:
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 ;
最后,您可以使用此函数计算两点之间的距离,并过滤最近的n
。我将使用用户变量来定义原点的纬度和经度:
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;