Frage zu ST_Cotains(a.geom, b.geom) = FALSE

Hallo,

für ein aktuelles Projekt möchte ich Gebiete (Polygone) hinsichtlich bestehender Tiersichtungen (Punkte) überprüfen. Zu diesem Zweck verwende ich ST_Contains:

CREATE VIEW gebiet_mit_sichtung AS
SELECT DISTINCT
gebiet.gid
gebiet.geom
FROM
gebiet, tiersichtung
WHERE
ST_Contains(gebiet.geom, tiersichtung.geom) = TRUE;

Mittels DISTINCT verhindere ich, dass ein Gebiet mit mehrfachen Tiersichtungen mehrfach ausgewählt wird. QGIS kann das Ergebnis in diesem Fall auch nicht darstellen. Diese Abfrage scheint soweit korrekt zu funktionieren. Allerdings gibt mir meine Abfrage “gebiet_ohne_sichtung” alle Geometrien der Tabelle “gebiet” aus. Warum das so ist, verstehe ich aktuell leider nicht.

CREATE VIEW gebiet_ohne_sichtung AS
SELECT DISTINCT
gebiet.gid
gebiet.geom
FROM
gebiet, tiersichtung
WHERE
ST_Contains(gebiet.geom, tiersichtung.geom) = FALSE;

Ich helfe mir daher mit einer Unterabfrage.

CREATE VIEW gebiet_ohne_sichtung AS
SELECT DISTINCT
gebiet.gid
gebiet.geom
FROM
gebiet, tiersichtung
WHERE gebiet.gid NOT IN
(SELECT DISTINCT
gebiet.gid
FROM
gebiet, tiersichtung
WHERE ST_Contains(gebiet.geom, tiersichtung.geom) = TRUE);

Gibt es auch eine elegantere Lösung?

Vielen Dank!

Ohne Kaffee und Gewähr:

select gebiet.gid, gebiet.geom
  from gebiet
    left join tiersichtung on not st_contains(gebiet.geom, tiersichtung.geom) 
  having count(tiersichtung.gid) = 0

Wäre eine Möglichkeit. Eine andere Möglichkeit wäre es eine extra Jointabelle mit den ids der beiden Tabellen zu erzeugen, die sich schneiden. Damit baut man eine korrekte m:n-Relation auf (unter der Annahme, das Gebiete und Tierbeobachtungen nicht die gleichen Geometrien benutzen und sich eine Beobachtung über mehrere Gebiete erstrecken kann, wie ich aus den vergangenen Fragen schliesse) und spart sich teure räumliche Abfragen im Wirkbtrieb.
Die gesuchten Gebiete ohne Beobachtung haben dann keinen Eintrag in der Jointabelle und lassen sich leicht filtern.

Gruß Uwe

Danke, ich habe mein Problem nun so gelöst:

CREATE VIEW gebiet_ohne_sichtung AS
SELECT
gebiet.gid, gebiet.geom
FROM
gebiet LEFT JOIN tiersichtung
ON ST_Contains(gebiet.geom, tiersichtung.geom)
WHERE tiersichtung.gid IS NULL;

Somit erhalte ich alle Polygone (Gebiete), welche keine Punkte (Tiersichtungen) enthalten. Außerem wird die Abfrage schneller als jene in meinem ersten Beitrag ausgeführt. Was ist denn davon zu halten?

So geht das auch gut solange die Anzahl der zu schneidenen Geometrien überschaubar bleibt. Für eine große Anzahl oder seltsam geformte Geometrien bei denen die BBox sehr viel größer ist als die Polygonfläche lohnt sich IMHO der Aufwand für eine Join-Tabelle.

Gruß Uwe