Начиная с некоторых случайных точек, в стремлении имитировать те, что на изображении ОП, где первые два пространственно пересекаются, затем вторые и третьи имеют одинаковый атрибут id (2) с парой других точек, которые пространственно не пересекаются и не имеют тот же атрибут, следующий запрос производит 3 кластера:
WITH
temp (id, geom) AS
(VALUES (1, ST_Buffer(ST_Makepoint(0, 0), 2)),
(2, ST_Buffer(ST_MakePoint(-0.7,0.5), 2)),
(2, ST_Buffer(ST_MakePoint(10, 10), 2)),
(3, ST_Buffer(ST_MakePoint(-2, 12), 2)),
(4, ST_Buffer(ST_MakePoint(5, -6), 2))),
unions(geoms) AS
(SELECT ST_Union(geom) FROM temp GROUP BY id),
clusters(geoms) AS
(SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3)
FROM unions),
multis(id, geoms) AS
(SELECT row_number() over() as id, geoms FROM clusters)
SELECT ST_UNION(d.geom) FROM
(SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;
Здесь есть несколько шагов:
- использовать
ST_Union
, группировать по идентификатору, для первой группы по атрибуту
- использовать
ST_ClusterIntersecting
для объединения тех же групп, которые пересекаются в пространстве
- добавить идентификатор для каждого из кластеров (таблица multis) - попытка сделать это непосредственно в ClusterIntersecting приводит к тому, что все геометрии получают идентификатор 1
- Объедините сброшенные геометрии из шага 2, сгруппировав их по идентификатору из шага 3 - это часть растворения . Это приводит к тому, что два перекрывающихся полигона в вашем кластере A объединяются, а не перекрываются, как это делается в конце шага 2.
Довольно долго, но это работает (и, я уверен, есть более короткий путь).
Использование инструмента WKT в QGIS (и обнаружение того, насколько я ужасен с инструментами редактирования) создает кластеры, подобные следующему, где вы можете видеть кластер, помеченный вами как a, - все вместе - то есть один цвет.
Если вы поместите ST_AsText вокруг финала, ST_UNION (d.geom), то вы сможете увидеть результаты напрямую.
РЕДАКТИРУЙТЕ, следуя дополнительной информации в комментариях: Поскольку вы начинаете с точек, вам нужно будет включить буфер в мое исходное решение, которое я поместил в временный CTE в начале, чтобы имитировать вашу диаграмму. Было бы проще добавить буфер в союзы CTE, чтобы вы могли выполнять все геометрические операции одновременно. Таким образом, используя в качестве примера буферное расстояние 1000, следующий код теперь возвращает 3 кластера, как и ожидалось.
WITH temp(id, geom) AS
(VALUES
(1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),
(2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),
(3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
(4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256))
),
unions(geoms) AS
(SELECT st_buffer(ST_Union(geom), 1000) FROM temp GROUP BY id),
clusters(geoms) AS
(SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3)
FROM unions),
multis(id, geoms) AS
(SELECT row_number() over() as id, geoms FROM clusters)
SELECT id, ST_UNION(d.geom) FROM
(SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;