PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Получаване на всички сгради в обхват от 5 мили от определени координати

Защо съхранявате x,y в отделни колони? Силно ви препоръчвам да ги съхранявате като geometry или geography за да избегнете ненужни режийни разходи по време на заявка.

Като се има предвид това, можете да изчислявате и проверявате разстоянията в мили, като използвате ST_DWithin или ST_Distance :

(Тестови данни)

CREATE TABLE building (name text, long numeric, lat numeric);
INSERT INTO building VALUES ('Kirk Michael',-4.5896,54.2835);
INSERT INTO building VALUES ('Baldrine',-4.4077,54.2011);
INSERT INTO building VALUES ('Isle of Man Airport',-4.6283,54.0804);

ST_DWithin

ST_DWithin връща true, ако дадените геометрии са в рамките на определеното разстояние от друга. Следната заявка търси геометрии, които са в радиус от 5 мили от POINT(-4.6314 54.0887) :

SELECT name,long,lat,
  ST_Distance('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat)) * 0.000621371 AS distance
FROM building
WHERE
  ST_DWithin('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat),8046.72); -- 8046.72 metres = 5 miles;

        name         |  long   |   lat   |     distance      
---------------------+---------+---------+-------------------
 Isle of Man Airport | -4.6283 | 54.0804 | 0.587728347062174
(1 row)

ST_Distance

Функцията ST_Distancegeography type parameters) ще върне разстоянието в метри . Използвайки тази функция, всичко, което трябва да направите, е да преобразувате метри в мили в крайна сметка.

Внимание :Разстояния в заявки, използващи ST_Distance се изчисляват в реално време и затова не използвайте пространствения индекс . Така че не се препоръчва използването на тази функция в WHERE клауза! Използвайте го по-скоро в SELECT клауза. Въпреки това примерът по-долу показва как може да се направи:

SELECT name,long,lat,
  ST_Distance('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat)) * 0.000621371 AS distance
FROM building
WHERE 
  ST_Distance('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat)) * 0.000621371 <= 5;

        name         |  long   |   lat   |     distance      
---------------------+---------+---------+-------------------
 Isle of Man Airport | -4.6283 | 54.0804 | 0.587728347062174
(1 row)
  • Внимавайте за реда на параметрите с ST_MakePoint :Това е дължина, ширина.. не обратното.

Демо:db<>fiddle

Еквивалент на Amazon Athena (разстояние в градуси):

SELECT *, ST_DISTANCE(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
      ST_POINT(long,lat)) AS distance
FROM building
WHERE 
  ST_Distance(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
  ST_POINT(long,lat)) <= 5;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Добавяне на едно от две ненулево ограничение в postgresql

  2. Какво се случва с дубликатите при вмъкване на няколко реда?

  3. Планетарно подравняване

  4. Инсталиране на Postgres на Windows за използване с Ruby-on-Rails

  5. sql ПОРЪЧАЙТЕ ПО множество стойности в определен ред?