纬度经度接近度计算中的Postgresql错误

Posted

技术标签:

【中文标题】纬度经度接近度计算中的Postgresql错误【英文标题】:Postgresql error in proximity calculation for latitude longitude 【发布时间】:2017-05-13 10:59:24 【问题描述】:

我在 postgresql 中有一个从这里导入的机场数据表:http://ourairports.com/data/

这是 DDL

create table flights.airports
(
id integer not null
    constraint airports_pkey
        primary key,
ident varchar(7) not null,
type varchar(14) not null,
name varchar(77) not null,
latitude_deg numeric(25,22) not null,
longitude_deg numeric(22,18) not null,
elevation_ft integer,
continent varchar(2) not null,
iso_country varchar(2) not null,
iso_region varchar(7) not null,
municipality varchar(60),
scheduled_service varchar(3) not null,
gps_code varchar(4),
iata_code varchar(3),
local_code varchar(7),
home_link varchar(128),
wikipedia_link varchar(128),
keywords varchar(256),
feed_url varchar(255),
created_at date,
input_line_num integer,
geom geometry(Point,4326)
)
;

以下是数据示例:

id  ident   type    name    latitude_deg    longitude_deg   elevation_ft    continent   iso_country iso_region  municipality    scheduled_service   gps_code    iata_code   local_code  home_link   wikipedia_link  keywords
6523    00A heliport    Total Rf Heliport   40.07080078 -74.93360138    11  NA  US  US-PA   Bensalem    no  00A     00A         
6524    00AK    small_airport   Lowell Field    59.94919968 -151.6959991    450 NA  US  US-AK   Anchor Point    no  00AK        00AK            
6525    00AL    small_airport   Epps Airpark    34.8647995  -86.77030182    820 NA  US  US-AL   Harvest no  00AL        00AL            
6526    00AR    closed  Newport Hospital & Clinic Heliport  35.6087 -91.254898  237 NA  US  US-AR   Newport no                      00AR

我正在使用以下 PostgreSQL Haversine 查询将最近的机场返回到给定的纬度/经度值:

SELECT * FROM flights.airports WHERE acos(sin(38.691055) * sin(latitude_deg) + cos(38.691055) * cos(latitude_deg) * cos(longitude_deg - (-121.233055))) * 6371 <= 1000;

来源:http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates

我在上面的查询中输入的值 (38.691055,-121.233055) 是 MC CLELLAN AIRFIELD(萨克拉门托)附近的一个点。

https://www.google.co.uk/maps/place/38°41'27.8"N+121°13'59.0"W/@38.691055,-121.3731307,11z/data=!4m5!3m4!1s0x0:0x0!8m2!3d38.691055!4d-121.233055?hl=en

但是,当我运行查询时,选择会返回以下数据,

迈尔斯菲尔德,39.8849983215332,-86.50669860839844

在印第安纳州,注意经度的差异。

https://www.google.co.uk/maps/dir/Myers+Field,+Lizton,+IN,+USA/38.691055,-121.233055/@39.8910608,-112.8731208,5z/data=!3m1!4b1!4m8!4m7!1m5!1m1!1s0x886cb47c5293f51b:0x29b57085edb34681!2m2!1d-86.5066666!2d39.8850438!1m0?hl=en

我已经测试了 CSV 数据,它很好,我已经检查了 hasrsine 查询,它看起来是一种标准方法,所以我假设问题是我存储/呈现的方式纬度和经度值,但我看不出我做错了什么。

【问题讨论】:

【参考方案1】:

您提供的链接中的公式使用弧度。在您的查询中,您使用的是度数。 尝试使用radian() 函数转换所有纬度和经度的单位。 您还交换了公式中的最后一个 long1 和 long2。

SELECT * 
FROM flights.airports 
WHERE acos(
       sin(radians(38.691055)) 
         * sin(radians(latitude_deg)) 
       + cos(radians(38.691055)) 
         * cos(radians(latitude_deg)) 
         * cos( radians(-121.233055)
           - radians(longitude_deg))
       ) * 6371 <= 1000;

【讨论】:

很遗憾,这也没有用。不过感谢您的建议。 @sadly:啊,最后两个经度在您的尝试中与源方程中的顺序不同。尝试更新的解决方案 仍然不对,我存储机场数据的纬度/经度的方式一定是我做错了,因为查询找到离38.691055最近的机场, -121.233055 返回以下内容:MC MANUS FIELD,33.4522018433,-96.8328018188,695 正确答案是MC CLELLAN AIRFIELD,38.66759872,-121.401001 添加缺少的右括号(就在 *6371 之前),上面的等式返回 2261km 到 33.4522018433,-96.8328018188

以上是关于纬度经度接近度计算中的Postgresql错误的主要内容,如果未能解决你的问题,请参考以下文章

当经度 > 90 时,Python 纬度/经度中点计算给出错误结果

球体表面(经度,纬度)点的凸包

纬度和经度的数据类型是啥?

怎么知道经纬度算距离,

基于纬度/经度查询附近兴趣点的 SQL 查询 - SQLite

SQL 2003 距离 纬度 经度