Calculating shortest distance between polygons?
You can use ST_ClusterDBSCAN to group nearby geometries together and assigning them a cluster id. Cluster ID will be null for single geometries not within the specified distance of another.
Image taken from the help section showing cluster IDs:
This query should return only the records within 1000 m of Another. minpoints := 2
is to prevent single points from getting a cluster ID (since they are always within the distance of themselves):
SELECT * FROM
(SELECT *, ST_ClusterDBSCAN(geom, eps := 1000, minpoints := 2) OVER () clusterid
FROM int_20190124) t1
WHERE t1.clusterid IS NOT NULL;
Example with points and 10000 m distance:
Here is my approach,
It is called "buffer clustering at the required distance"
(do not beat off the fish from the pack at the specified distance, and then we will eat you :-)),
It consists of 6 points, swam...
The source data shown in figure 1
It is polygons of polygon type. Restrictions, example, are shown without object semantics, so that you can save it yourself.
1) Create a buffer equal to almost half the required distance, for example 501 m:
create table polygons_byf as
SELECT ((ST_Buffer(geography(geom),501))::geometry) as geom
FROM polygons;
2) Dissolving polygon:
create table polygons_byf_dump as
select st_buffer(
(st_dump(
st_union(
st_buffer(geom, 0.0000000001)))).geom, -0.0000000001) as geom
FROM polygons_byf;
(John Powell :-)...)
see figure 2
3) Create the median point to the original polygon:
create table polygons_byf_centr as
SELECT ST_PointOnSurface(geom) as geom
FROM polygons;
see figure 3
4) Count the number of points that fall into the combined polygons:
create table polygons_pt_count as
SELECT
b.geom,
count (*) as cnt
FROM polygons_byf_centr a, polygons_byf_dump b
WHERE
st_intersects(a.geom, b.geom)
GROUP BY b.geom
ORDER BY b.geom;
see figure 4
5) Delete polygons that have only one point:
DELETE from polygons_pt_count
WHERE cnt = '1';
see figure 5
6) Select only those polygons that meet our condition:
create table polygons_sel as
SELECT ST_Intersection(a.geom, b.geom) as geom
FROM polygons_pt_count a, polygons as b
WHERE ST_Intersects (a.geom, b.geom)
see figure 6
7) That's all; this is our result.
SELECT id
FROM polygons
WHERE id IN (
SELECT
p1.id
FROM polygons p1
JOIN polygons p2 ON (ST_DWithin(p1.geom, p2.geom, 1000))
WHERE p1.id <> p2.id
);
You can join polygons on ST_Dwithin to find these being at most one km far from others. Note distance being used is given in SRID units, so be careful when using degrees.
I assume GIST index on geom
field as well as PRIMARY KEY
on id
field exists. As stated in docs, ST_Dwithin includes bbox comparison and generally speaking, it should be faster than building buffers around the input geometries.