Защо съхранявате 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_Distance
(с geography
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;