ST_ClusterWithin
What is ST_ClusterWithin?
ST_ClusterWithin is a PostGIS aggregate function that groups input geometries into clusters using single-linkage clustering by distance. Any two geometries within the supplied distance threshold are in the same cluster; clusters merge transitively through chains of nearby geometries.
1ST_ClusterWithin(geometry set g, float8 distance) → geometry[]
2ST_ClusterWithin(geometry[] g, float8 distance) → geometry[]The result is an array of GeometryCollections, one per cluster.
When would you use ST_ClusterWithin?
Use ST_ClusterWithin to merge features that are close enough to treat as a single group — grouping buildings within walking distance, collecting sensor readings into location-based bins, or merging overlapping or near-touching polygons. It is the distance-based cousin of ST_ClusterIntersecting.
1SELECT (ST_Dump(g)).geom AS cluster_member
2FROM (
3 SELECT unnest(ST_ClusterWithin(geom, 50)) AS g
4 FROM bus_stops
5) t;FAQs
What units is the distance in?
The same units as the input geometry's SRID — metres for projected CRSs, degrees for geographic CRSs like EPSG:4326. For a 50-metre threshold on lat/lon data, reproject to a metric CRS first.
How is this different from ST_ClusterDBSCAN?
ST_ClusterWithin is single-linkage clustering: any two features within distance join the same cluster, and small sparse groups are kept. ST_ClusterDBSCAN adds a minpoints threshold to reject sparse groups as noise and is better at avoiding "chaining" artefacts in noisy data.
When should I use this over ST_ClusterIntersecting?
Use ST_ClusterIntersecting when you want to join only features that actually touch or overlap (distance = 0). Use ST_ClusterWithin when proximity — not strict touching — defines the clusters.
How do I get a single dissolved polygon per cluster?
Wrap each cluster collection with ST_Union: SELECT ST_Union(ST_CollectionExtract(g, 3)) FROM unnest(ST_ClusterWithin(geom, 50)) g. That dissolves each cluster's geometries into a single polygon or multipolygon.