我有latitude
和longitude
列在location
列在PostgreSQL数据库中, 我试图用PostgreSQL函数执行距离查询。PostgreSQL经纬度查询
我阅读手册的这一章:
https://www.postgresql.org/docs/current/static/earthdistance.html
,但我觉得我失去了一些东西在那里。
我该怎么做?是否有更多示例可用
我有latitude
和longitude
列在location
列在PostgreSQL数据库中, 我试图用PostgreSQL函数执行距离查询。PostgreSQL经纬度查询
我阅读手册的这一章:
https://www.postgresql.org/docs/current/static/earthdistance.html
,但我觉得我失去了一些东西在那里。
我该怎么做?是否有更多示例可用
此模块是可选的,并未安装在默认的PostgreSQL instalatlion中。您必须从contrib目录安装它。
您可以使用下面的函数来计算坐标之间的大致距离(英里):
CREATE OR REPLACE FUNCTION distance(lat1 FLOAT, lon1 FLOAT, lat2 FLOAT, lon2 FLOAT) RETURNS FLOAT AS $$
DECLARE
x float = 69.1 * (lat2 - lat1);
y float = 69.1 * (lon2 - lon1) * cos(lat1/57.3);
BEGIN
RETURN sqrt(x * x + y * y);
END
$$ LANGUAGE plpgsql;
假设你已经正确安装了earthdistance模块,这会给你两个城市之间的英里的距离。该方法使用更简单的基于点的地球距离。请注意,point()的参数是第一个经度,然后是纬度。
create table lat_lon (
city varchar(50) primary key,
lat float8 not null,
lon float8 not null
);
insert into lat_lon values
('London, GB', 51.67234320, 0.14787970),
('New York, NY', 40.91524130, -73.7002720);
select
(
(select point(lon,lat) from lat_lon where city = 'London, GB') <@>
(select point(lon,lat) from lat_lon where city = 'New York, NY')
) as distance_miles
distance_miles
--
3447.58672105301
中谢谢,此答案是执行此操作的最佳方法。你只需要运行'CREATE EXTENSION cube; CREATE EXTENSION earthdistance;'安装earthdistance。 – sudo 2015-07-27 23:51:15
下面是使用点操作又如:
create extension cube;
create extension earthdistance;
select (point(-0.1277,51.5073) <@> point(-74.006,40.7144)) as distance;
distance
------------------
3461.10547602474
(1 row)
注意points
与经度FIRST创建。根据documentation:
因为经度更接近直观的x轴和纬度到y轴,所以点取经度,纬度,反之亦然。
这是可怕的设计......但是就是这样。
得到了一个清洁比基于'earthdistance'的其他答案投票 – igorsantos07 2015-11-22 05:24:49
谢谢你,伟大的解决方案! – Bagdat 2016-06-18 19:50:58
@ strkol的回答的一个更精确的版本,使用Haversine formula
CREATE OR REPLACE FUNCTION distance(
lat1 double precision,
lon1 double precision,
lat2 double precision,
lon2 double precision)
RETURNS double precision AS
$BODY$
DECLARE
R integer = 6371e3; -- Meters
rad double precision = 0.01745329252;
φ1 double precision = lat1 * rad;
φ2 double precision = lat2 * rad;
Δφ double precision = (lat2-lat1) * rad;
Δλ double precision = (lon2-lon1) * rad;
a double precision = sin(Δφ/2) * sin(Δφ/2) + cos(φ1) * cos(φ2) * sin(Δλ/2) * sin(Δλ/2);
c double precision = 2 * atan2(sqrt(a), sqrt(1-a));
BEGIN
RETURN R * c;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
输入是在度(例如52.34273489,6.23847)和输出是在米。
你能解释一下这里的数学吗? 69.1和57.3代表什么? – jamesfzhang 2013-07-15 18:00:44
我会想象它们是用来将纬度和经度转换为英里的常量。 – 2013-09-24 16:05:41
要使用KM而不是英里数,请使用常量111.12和92.215来替换69.1和57.3 – 2014-06-09 23:19:30