PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Obtendo todos os edifícios no alcance de 5 milhas de coordenadas especificadas


Por que você está armazenando x,y em colunas separadas? Eu sugiro fortemente que você os armazene como geometry ou geography para evitar sobrecarga de conversão desnecessária no tempo de consulta.

Dito isso, você pode calcular e verificar distâncias em milhas usando ST_DWithin ou ST_Distance :

(Dados de teste)
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 retorna true se as geometrias fornecidas estiverem dentro da distância especificada de outra. A consulta a seguir procura geometrias que estão em um raio de 5 milhas 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_Distância


A função ST_Distance (com geography parâmetros de tipo) retornará a distância em metros . Usando esta função, tudo o que você precisa fazer é converter metros em milhas no final.

Atenção :distâncias em consultas usando ST_Distance são calculados em tempo real e, portanto, não use o índice espacial . Portanto, não é recomendado usar esta função no WHERE cláusula! Use-o no SELECT cláusula. No entanto, o exemplo abaixo mostra como isso poderia ser feito:
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)
  • Lembre-se da ordem dos parâmetros com ST_MakePoint :É longitude,latitude.. não ao contrário.

Demonstração:db<>fiddle

Equivalente ao Amazon Athena (distância em graus):
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;