Запрос долготы долготы PostgreSQL - программирование
Подтвердить что ты не робот

Запрос долготы долготы PostgreSQL

У меня есть столбцы latitude и longitude в таблице location в базе данных PostgreSQL, и я пытаюсь выполнить запрос расстояния с помощью функции PostgreSQL.

Я прочитал эту главу руководства:

https://www.postgresql.org/docs/current/static/earthdistance.html

но я думаю, что там что-то не хватает.

Как мне это сделать? Есть ли еще примеры доступных

4b9b3361

Ответ 1

Этот модуль является необязательным и не установлен в стандартном instalatlion 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;

Ответ 2

Вот еще один пример использования точечного оператора:

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.

Какой ужасный дизайн... но так, как есть.

Ответ 3

Предполагая, что вы правильно установили модуль заземления, это даст вам расстояние в милях между двумя городами. Этот метод использует более простые наземные расстояния на основе точек. Обратите внимание, что аргументы точки() - это первая долгота, затем широта.

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

Ответ 4

Более точная версия ответа @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), а выход - в метрах.