Berechnung der prozentualen Schnittfläche in der where-Klausel


15

Ich habe eine Tabelle mit Polygonen (Zensusblockgruppen) in Postgres. Ich möchte jede Blockgruppe mit der Stadt (einer anderen Polygontabelle) versehen, in der sie sich hauptsächlich befindet. Ist das möglich? Ich denke, ich müsste im Wesentlichen Folgendes erstellen:

select b.*,t.name  
from blockgroups b, towns t  
where (st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) > .5  

aber diese Abfrage dauert ewig (ich habe ungefähr 5.000 Blockgruppen und 375 Städte ...). Irgendwelche Vorschläge, wie diese Abfrage funktioniert, wenn sie falsch ist oder schneller, wenn sie korrekt ist?


Klingt so, als ob Sie die Blockgruppen anhand der maximalen Überlappung markieren möchten? Wenn ja, lesen Sie diese Antwort . Wenn es sich bei Ihren Städten auch um Zensus-Geografien (z. B. MCDs oder Orte) handelt, muss der Überlappungsprozentsatz wahrscheinlich nicht berechnet werden.
Dbaston

Antworten:


22

Die Art und Weise, wie Sie es tun, wird funktionieren, aber es wird zu viel Zeit in Anspruch nehmen, da postgis versucht, die Geometrie der Schnittpunkte jeder Kombination aus "Blockgruppe und Stadt" zu erstellen, selbst wenn sie sich nicht einmal berühren.

Fügen Sie Ihrer WHERE-Klausel eine weitere Bedingungsüberprüfung hinzu, um zu überprüfen, ob die beiden Geometrien sich überschneiden, und setzen Sie sie vor die vorhandene:

select b.*,t.name
from blockgroups b, towns t
where st_intersects(b.wkb_geometry, t.wkb_geometry) and    
    (st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) > .5

Wenn Sie in SQL eine Liste von Bedingungen in der WHERE-Klausel haben, werden diese in der Reihenfolge getestet, in der sie geschrieben werden. Wenn in einem der frühen Vorgänge ein FALSE zurückgegeben wird, überspringt die Abfrage nur die Prüfung der anderen Bedingungen, da das Ergebnis immer FALSE ist.

Stellen Sie außerdem sicher, dass Sie über räumliche Indizes für blockgroups.wkb_geometry und towns.wkb_geometry verfügen.


1
Das Hinzufügen ST_Intersectsist hier der richtige Weg, aber der Planer kann die Bedingungen in der Reihenfolge ausführen, in der sie geschrieben wurden, oder auch nicht. Weitere Informationen hierzu finden Sie in den Postgres- Dokumenten . ST_IntersectsUnd ST_Intersectionich habe die gleichen Kosten für meine Installation (100). Um ehrlich zu sein, bin ich mir nicht sicher, was der Planer tut, aber es scheint hier immer das Richtige zu tun.
Dbaston

Ahh ... Ich bin davon ausgegangen, dass die Bedingungen wie in anderen Sprachen überprüft werden. Aber ich denke, es gibt dem Planer eine andere Option.
Alexandre Neto

9

Wenn sich einige Ihrer Zensuseinheiten über drei Ihrer Städte erstrecken (und Sie daher nicht mehr als 50% Stürze in einer Stadt garantieren können), können Sie dies zu Alexandres sehr nützlicher Antwort hinzufügen:

select distinct on (b.id)
b.*,t.name,
(st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) as proportion
from blockgroups b, towns t
where st_intersects(b.wkb_geometry, t.wkb_geometry) 
order by b.id, proportion desc;

Dies schützt grundsätzlich vor folgender Situation - in der die Bereiche in Blau verschwinden würden: Bildbeschreibung hier eingeben


1
Ich finde es absolut klasse, wenn das erste Problem, auf das ich mit einer SO-Antwort stoße, mit der nächsten Antwort gelöst wird. Prost, @RobinL!
Wfgeo

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.