Я пытаюсь использовать ST_Difference для создания набора полигонов (processing.trimmedparcelsnew), которые не содержат области, покрытой другим набором полигонов (test.single_geometry_1), используя PostGis 2.1 (и Postgres SQL 9.3). Вот мой запрос:
CREATE TABLE processing.trimmedparcelsnew AS
SELECT
orig.id, ST_Difference(orig.geom, cont.geom) AS difference
FROM
test.single_geometry_1 cont,
test.multi_geometry_1 orig;
Но полученные многоугольники не были обрезаны, вместо этого они, кажется, были разделены там, где они пересекаются с другим слоем. Я пытался просто запустить select, не помещая результат в таблицу и все остальное, что я могу придумать, но я не могу заставить эту функцию работать.
Я приложил картину результата
После комментариев я попытался добавить предложение WHERE. Я хочу, чтобы участки, у которых нет пересечений, и области пересечения других участков были удалены (слой test.single_geometry представляет загрязнение, которое я хочу удалить из своих участков). Я попытался пересечь, но, конечно, я на самом деле хочу, чтобы пересечения не пересекались, поэтому я сейчас пытаюсь пересечь. Я также попытался добавить orig к моей таблице, но документация для ST_Difference ( http://postgis.net/docs/ST_Difference.html ) говорит, что она возвращает именно ту геометрию, которая мне нужна (геометрия, которая представляет ту часть геометрии A, которая не пересекается с геометрией B), поэтому я не понимаю, зачем мне вместо этого исходный многоугольник в моей таблице. В любом случае, вот мой модифицированный код:
CREATE TABLE processing.trimmedparcelsnew AS
SELECT
orig.id, ST_Difference(orig.geom, cont.geom) AS difference, orig.geom AS geom
FROM
test.single_geometry_1 cont,
test.multi_geometry_1 orig
WHERE ST_Disjoint(orig.geom, cont.geom);
Исходя из ответа dbaston, я попробовал:
CREATE TABLE processing.parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom)
FROM test.single_geometry_1 b
WHERE ST_Intersects(a.geom, b.geom)
AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;
Результатом этого является просто копия test.multi_geometry_1. Хотя сейчас расщепление больше не происходит.
Я пробовал более раннюю версию, но снова просто получить копию test.multi_geometry_1:
CREATE TABLE processing.parcels_trimmed_no_coalesce AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom)
FROM test.single_geometry_1 b
WHERE ST_Intersects(a.geom, b.geom)
AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;
Я начинаю задаваться вопросом, есть ли что-то еще, что я делаю неправильно? Исходное заявление:
DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;
И я выполняю запросы из окна SQL-запросов PostgreSQL и Openjump.
Утверждение, которое я использую, чтобы увидеть таблицу:
SELECT * FROM processing.parcels_trimmed_no_coalesce;
В целях упрощения я теперь сократил этот запрос до просто:
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom)
FROM test.geometriestocutagainst b
WHERE ST_Intersects(a.geom, b.geom)
AND a.id != b.id)), a.geom)
FROM test.geometriestocut a;
Это по-прежнему приводит только к оригинальным полигонам (test.geometriestocut), когда желаемый результат - это оригинал, обрезанный по test.geometriestocutagainst.
WHERE
предложение, поэтому вы можете иметь полиномиальное расширение в результирующей таблице. Сколько строк вtrimmedparcelsnew
?Ответы:
Самостоятельное соединение позволяет вам управлять отношениями между парами двух функций. Но я не думаю, что вас интересуют пары: для каждой функции вы хотите оперировать отношениями между этой функцией и всеми другими функциями в вашем наборе данных. Вы можете сделать это с помощью выражения подзапроса:
Вы можете увидеть что-то странное в результатах. Посылки, которые не имеют перекрытий, удаляются полностью! Это потому, что
ST_Union
агрегат на пустом наборе записей будетNULL
иST_Difference(geom, NULL)
естьNULL
. Чтобы сгладить это, вам нужно заключить вашST_Difference
звонок вCOALESCE
:Это означает, что если результатом
ST_Difference
являетсяNULL
, объединенное выражение будет вычислять исходную геометрию.Приведенный выше запрос полностью удалит перекрывающиеся области из вашего домена. Если вы вместо этого хотите выбрать победителя, вы можете использовать
a.id < b.id
другой критерий вместоa.id != b.id
.источник
У меня была такая же проблема, как и у вас. Я не знаю, нашли ли вы решение вашей проблемы, но я изменил принятый ответ выше и получил то, что хотел.
источник
Я использую ST_DifferenceAgg () из дополнений PostGIS . Вы должны объединить две таблицы вместе, иметь уникальный идентификатор и индекс в столбце геометрии. Вот краткий пример:
Это объединит перекрывающиеся части с самым большим перекрывающимся многоугольником. Если вы хотите оставить перекрывающуюся часть отделенной, посмотрите на пример ST_splitAgg ().
источник