Pourquoi stockez-vous x,y dans des colonnes séparées ? Je vous suggère fortement de les stocker en tant que geometry
ou geography
pour éviter une surcharge de casting inutile au moment de la requête.
Cela étant dit, vous pouvez calculer et vérifier les distances en miles en utilisant ST_DWithin
ou ST_Distance
:
(Données de test)
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
renvoie vrai si les géométries données sont à la distance spécifiée les unes des autres. La requête suivante recherche les géométries situées dans un rayon de 8 km à partir de 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
La fonction ST_Distance
(avec geography
paramètres de type) renverra la distance en mètres . En utilisant cette fonction, tout ce que vous avez à faire est de convertir les mètres en miles à la fin.
Attention :Distances dans les requêtes utilisant ST_Distance
sont calculés en temps réel et donc n'utilisent pas l'index spatial . Il est donc déconseillé d'utiliser cette fonction dans le WHERE
clause! Utilisez-le plutôt dans le SELECT
clause. Néanmoins, l'exemple ci-dessous montre comment cela pourrait être fait :
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)
- Attention à l'ordre des paramètres avec
ST_MakePoint
:C'est la longitude, la latitude.. pas dans l'autre sens.
Démo :db<>fiddle
Équivalent Amazon Athena (distance en degrés) :
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;