Varför lagrar du x,y i separerade kolumner? Jag rekommenderar starkt att du lagrar dem som geometry
eller geography
för att undvika onödig casting overhead i frågetid.
Som sagt, du kan beräkna och kontrollera avstånd i miles med ST_DWithin
eller ST_Distance
:
(Testdata)
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
returnerar sant om de givna geometrierna är inom det specificerade avståndet från en annan. Följande fråga söker efter geometrier som är inom 5 miles radie från 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
Funktionen ST_Distance
(med geography
typparametrar) returnerar avståndet i meter . Allt du behöver göra med den här funktionen är att konvertera meter till miles till slut.
Obs :Avstånd i frågor med ST_Distance
beräknas i realtid och använder därför inte det rumsliga indexet . Så det rekommenderas inte att använda den här funktionen i WHERE
klausul! Använd den hellre i SELECT
klausul. Icke desto mindre visar exemplet nedan hur det skulle kunna göras:
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)
- Ta hänsyn till parametrarnas ordning med
ST_MakePoint
:Det är longitud,latitud.. inte tvärtom.
Demo:db<>fiddle
Amazon Athena-ekvivalent (avstånd i grader):
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;