Próbuję użyć ST_Difference do utworzenia zestawu wielokątów (processing.trimmedparcelsnew), które nie zawierają żadnego obszaru objętego innym zestawem wielokątów (test.single_geometry_1) przy użyciu PostGis 2.1 (i Postgres SQL 9.3). Oto moje zapytanie:
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;
Ale powstałe wielokąty nie zostały przycięte, zamiast tego wydają się być podzielone tam, gdzie przecinają się z drugą warstwą. Próbowałem właśnie uruchomić selekcję bez umieszczania wyniku w tabeli i wszystkim innym, o czym mogę myśleć, ale wydaje mi się, że nie mogę uruchomić tej funkcji.
Dołączyłem zdjęcie wyniku
Po komentarzach próbowałem dodać klauzulę WHERE. Chcę usunąć działki, które nie mają przecięć, a przecinające się obszary innych działek zostały usunięte (warstwa test.single_geometry reprezentuje zanieczyszczenie, które chcę usunąć z moich działek). Próbowałem przecięcia, ale oczywiście chcę nie przecięcia, więc teraz próbuję rozłączenia. Próbowałem również dodać orig do mojej tabeli, ale dokumentacja ST_Difference ( http://postgis.net/docs/ST_Difference.html ) mówi, że zwraca dokładną geometrię, której potrzebuję (geometria reprezentująca tę część geometrii A, która nie przecina się z geometrią B), więc jestem zdezorientowany, dlaczego zamiast tego chcę mieć oryginalny wielokąt w mojej tabeli. W każdym razie oto mój zmodyfikowany kod:
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);
W odpowiedzi na odpowiedź dbaston próbowałem teraz:
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;
Wynikiem tego jest tylko kopia test.multi_geometry_1. Chociaż teraz podział już nie występuje.
Próbowałem wcześniejszej wersji, ale ponownie otrzymuję kopię 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;
Zaczynam się zastanawiać, czy coś jeszcze robię źle? Oświadczenie jest następujące:
DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;
I uruchamiam zapytania z okna zapytań SQL PostgreSQL i Openjump.
Oświadczenie, którego używam do zobaczenia tabeli to:
SELECT * FROM processing.parcels_trimmed_no_coalesce;
W celu uproszczenia ograniczyłem teraz tę kwerendę do:
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;
To wciąż powoduje powstanie tylko oryginalnych wielokątów (test.geometriestocut), gdy pożądanym wynikiem jest oryginalny przycięty względem test.geometriestocutagainst.
źródło
WHERE
klauzuli, więc w tabeli wynikowej może wystąpić rozwinięcie wielomianowe. Ile jest rzędówtrimmedparcelsnew
?Odpowiedzi:
Samozłączenie pozwala operować na relacji między parami dwóch funkcji. Ale nie sądzę, że jesteś zainteresowany parami: dla każdej funkcji chcesz operować relacją między tą funkcją a wszystkimi innymi funkcjami w zestawie danych. Możesz to zrobić za pomocą wyrażenia podkwerendowego:
W wynikach możesz jednak zobaczyć coś dziwnego. Paczki, które nie mają żadnych zakładek, są całkowicie usuwane! To dlatego, że
ST_Union
agregacja na pustym zestawie rekordów będzieNULL
i takST_Difference(geom, NULL)
będzieNULL
. Aby to złagodzić, musisz zawinąćST_Difference
połączenie wCOALESCE
:Oznacza to, że jeśli wynikiem
ST_Difference
jestNULL
, wyrażenie połączone zostanie ocenione do oryginalnej geometrii.Powyższe zapytanie całkowicie usunie nakładające się obszary z domeny. Jeśli zamiast tego chcesz wybrać zwycięzcę, możesz
a.id < b.id
zamiast tego zrobić inne kryteriuma.id != b.id
.źródło
Miałem ten sam problem co ty. Nie wiem, czy już znalazłeś rozwiązanie swojego problemu, ale zmodyfikowałem zaakceptowaną odpowiedź powyżej i dostałem to, czego chciałem.
źródło
Używam ST_DifferenceAgg () z PostGIS Addons . Musisz połączyć dwie tabele razem, mieć unikalny identyfikator i indeks w kolumnie geometrii. Oto krótki przykład:
Spowoduje to scalenie zachodzących na siebie części z największym zachodzącym wielokątem. Jeśli chcesz zachować zachodzące na siebie części, spójrz na przykład ST_splitAgg ().
źródło