PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Obtenir tous les bâtiments à une distance de 5 miles des coordonnées spécifiées

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;