Si se quiere evitar una extensión de SIG, que adapta las funciones de this post a postgres sql:
create or replace function change_in_lat(miles numeric)
returns double precision as $$
with v as (select
3960.0 as earth_radius,
180/pi() as radians_to_degrees
) select (miles/earth_radius) * radians_to_degrees from v;
$$ language sql
returns null on null input;
create or replace function change_in_long(lat numeric, miles numeric)
returns double precision as $$
with v as (select
3960.0 as earth_radius,
pi()/180 as degrees_to_radians,
180/pi() as radians_to_degrees
) select (
miles/(earth_radius * cos(lat * degrees_to_radians))
) * radians_to_degrees from v;
$$ language sql
returns null on null input;
mediante los que se pueden hacer algunas cuadrados que rodean consultas:
--find all "a"s within 25 miles of any "b"
select * from a join b on (
a.gpslat between
b.gpslat - change_in_lat(25) and b.gpslat + change_in_lat(25)
and a.gpslong between
b.gpslong - change_in_long(b.gpslat::numeric, 25)
and b.gpslong + change_in_long(b.gpslat::numeric, 25)
);
si se quiere lo usé con la frecuencia suficiente. Estoy seguro de que sería fácil convertir las declaraciones entre en una sola función. Sin embargo, nunca realicé consultas reales "dentro del radio" con esto.
Para algo más complicado, es probable que desee una extensión GIS como han dicho otras respuestas. PostGIS es bueno, pero encontré que muchas de las funciones específicas de gis pueden ser difíciles de entender, y a menos que utilice índices de cuadro delimitador, sus consultas espaciales pueden demorar un día si su conjunto de datos es lo suficientemente grande. Pero la compensación en complejidad definitivamente vale la pena por todas las cosas sofisticadas, como la salida de datos en formato Geojson, etc.