Maybe you can try an iterative approach:
You first use ST_ClusterDBSCAN with a big eps and a small minpoints, and then you isolate the points that are in a cluster too big for you, for exemple using the radius of the bounding circle (general idea, not tested):
sqrt(ST_Area(ST_MinimumBoundingCircle(ST_Collect(points)))/pi) > your_threshold group by cluster_number
Then you do an other ST_ClusterDBSCAN on them with more stricts parameters (shorter eps and/or bigger minpoints). The main difficulty here relies on the choosing of how many steps and what parameters for each step, it depends on the actual result that you want.
If you do that a couple of time you should in fine have only small clusters, without loosing the aggregation in sparser areas.
EDIT: in my idea, that would look like that (I used max_cluster_id_big in the end to be sure the cluster id doesn't overlap):
INSERT INTO villages_clustered
WITH big_cluster_element AS (
SELECT
ROW_NUMBER() OVER() as id,
name,
way,
ST_ClusterDBSCAN(way, eps := 2000, minpoints := 1) over () AS cluster_id_big,
geom
FROM villages
), big_cluster AS (
SELECT
cluster_id_big,
sqrt(ST_Area(ST_MinimumBoundingCircle(ST_Collect(geom)))/pi()) as radius
FROM big_cluster_element
GROUP BY cluster_id_big
), big_cluster_element_with_radius AS (
SELECT
id,
name,
way,
bc.radius,
bce.cluster_id_big
geom
FROM big_cluster_element bce
LEFT JOIN big_cluster bc
ON bce.cluster_id_big=bc.cluster_id_big
), small_cluster_element AS (
SELECT
id,
name,
way,
ST_ClusterDBSCAN(way, eps := 500, minpoints := 3) over () AS cluster_id_small,
geom
FROM big_cluster_element_with_radius bc
WHERE bc.radius > 10000
), max_id_big AS (
SELECT
max(cluster_id_big) as max_cluster_id_big
FROM big_cluster_element
)
SELECT
id,
name,
way,
coalesce(cluster_id_small+max_cluster_id_big, cluster_id_big) as cluster_id,
geom
FROM max_id_big, big_cluster_element bce
LEFT JOIN small_cluster_element sce
ON bce.id = sce.id
epsparameter :) You say you want 10km clusters, so try an appropriate value for that. You have to take care of your coordinate values, which SRID is your data in if it is Geometries, not Geographies? Also you might like https://postgis.net/docs/manual-dev/ST_ClusterWithin.html as easier approach. – bugmenot123 Jul 23 '19 at 09:46ST_ClusterWithin?!? Cause it only returns clustered geometries?!? Right? So how could I get back to the villages themselfs? Yes... the eps is not stable, right? It will vary depending how far away from the equator I am? The thing is that some, or even most clusters seem to be about 10km. But some are waaaaay bigger, which I don't understand. The srid of my data is: 3857 – Georg Jul 23 '19 at 13:05eps, I don't get those huge clusters any more. But still, I have a lot of geometries that then don't have any cluster, even though there are other villages nearby – Georg Jul 23 '19 at 14:00epsunits from eitherminpointsother clustered points, or of a point that does (or getsNULL). consider points in a line around the globe, each no more thanepsunits apart; it can be one single cluster. that's what's happening here;St_ClusterDBSCANcannot find 'weighted' clusters, you'd need a different approach for that (kmeans?). with EPSG:3857,epsunit is meter (measures are heavily distorted towards the poles, but the impact should be small for the span of latitudes covering e.g. Slovenia) – geozelot Jul 23 '19 at 23:00ST_Clusterwhere not the ones I was looking for. I did split up the world in sectors (like tiling with maps works) and then used those as my "clusters". For the solution I needed, that was fine enough... – Georg Oct 02 '20 at 06:50