sql >> Base de Datos >  >> RDS >> PostgreSQL

Obtener todos los edificios en un rango de 5 millas desde las coordenadas especificadas

¿Por qué estás almacenando x,y? en columnas separadas? Le sugiero encarecidamente que los almacene como geometry o geography para evitar una sobrecarga de conversión innecesaria en tiempo de consulta.

Dicho esto, puede calcular y verificar distancias en millas usando ST_DWithin o ST_Distance :

(Datos de prueba)

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 devuelve verdadero si las geometrías dadas están dentro de la distancia especificada de otra. La siguiente consulta busca geometrías que están en un radio de 5 millas desde 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 función ST_Distance (con geography parámetros de tipo) devolverá la distancia en metros . Con esta función, todo lo que tiene que hacer es convertir los metros a millas al final.

Atención :Distancias en consultas usando ST_Distance se calculan en tiempo real y, por lo tanto, no utilizan el índice espacial . Por lo tanto, no se recomienda utilizar esta función en WHERE ¡cláusula! Úselo en lugar de SELECT cláusula. No obstante, el siguiente ejemplo muestra cómo podría hacerse:

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)
  • Observe el orden de los parámetros con ST_MakePoint :Es longitud, latitud... no al revés.

Demostración:db<>fiddle

Equivalente de Amazon Athena (distancia en grados):

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;