我在 PostgreSQL 数据库的表中有latitude
列longitude
,location
我正在尝试使用 PostgreSQL 函数执行距离查询。
我阅读了手册的这一章:
https://www.postgresql.org/docs/current/static/earthdistance.html
但我想我在那里遗漏了一些东西。
我该怎么做?是否有更多可用示例
我在 PostgreSQL 数据库的表中有latitude
列longitude
,location
我正在尝试使用 PostgreSQL 函数执行距离查询。
我阅读了手册的这一章:
https://www.postgresql.org/docs/current/static/earthdistance.html
但我想我在那里遗漏了一些东西。
我该怎么做?是否有更多可用示例
这是使用点运算符的另一个示例:
初始设置(只需运行一次):
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
是使用LONGITUDE FIRST创建的。根据文档:
点被视为(经度,纬度)而不是反之亦然,因为经度更接近 x 轴的直观概念,纬度更接近 y 轴。
这是糟糕的设计......但就是这样。
您的输出将以英里为单位。
给出地球表面上两点之间的法定英里距离。
此模块是可选的,未安装在默认的 PostgreSQL 安装中。您必须从 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;
使用Haversine 公式的@strkol 答案的更准确版本
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),输出以米为单位。
假设您已正确安装 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
另一种 Haversine 公式,返回里程。(来源)
CREATE OR REPLACE FUNCTION public.geodistance(
latitude1 double precision,
longitude1 double precision,
latitude2 double precision,
longitude2 double precision)
RETURNS double precision AS
$BODY$
SELECT asin(
sqrt(
sin(radians($3-$1)/2)^2 +
sin(radians($4-$2)/2)^2 *
cos(radians($1)) *
cos(radians($3))
)
) * 7926.3352 AS distance;
$BODY$
LANGUAGE sql IMMUTABLE
COST 100;