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;