Dies ist eine scheinbar einfache SQL Server-Geometriefrage, von der ich dachte, dass sie eine sofort einsatzbereite Lösung hätte, aber ich habe kein Glück, eine zu finden.
Meine Absicht ist es, alle Datensätze in einer Tabelle mit Polygonen auszuwählen, die in einem größeren Polygon aus einer anderen Tabelle verschachtelt (enthalten) sind. Ich hatte Funktionen erwartet STWithin
und STContains
als die Lösungen, die ich brauchte, aber leider identifizieren beide nur die inneren Polygone innerhalb derjenigen, die im größeren Polygon verschachtelt sind, nicht jene verschachtelten Polygone, die die Grenze des größeren Polygons berühren. Siehe Bild zum Beispiel.
Eine alternative Option, die meinen Bedürfnissen entsprach, war STIntersection
. Das Problem bei dieser Funktion ist jedoch, dass nur die Geometriespalte zurückgegeben wird! Ich möchte stattdessen die Datensatz-ID erhalten. Hat jemand einen Vorschlag, wie dies getan werden kann?
STWithin
::
select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STWithin(b.shape) = 1
where b.mktname = 'Loop'
STContains
::
select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on b.shape.STContains(a.shape) = 1
where b.mktname = 'Loop'
STIntersection
::
select a.shape.STIntersection(b.shape)
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'
Bearbeiten:
Ein Vorschlag war, STIntersection
ausschließlich STIntersects
Folgendes wegzulassen und zu verwenden :
STIntersects
::
select a.bg10
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'
Das Problem bei diesem Ansatz besteht darin, dass STIntersects
anscheinend alle Polygone entweder innerhalb oder außerhalb ausgewählt werden und das größere Polygon berührt wird, nicht nur die ausschließlich innerhalb. Siehe Bild zum Beispiel.
quelle
STContains
oder verwendenSTWithin
. Kein wirklich guter Hack, aber Sie erhalten die gewünschten Ergebnisse. Die andere Möglichkeit wäre, die STIntersects mit einem Vergleich des Intersection-Bereichs und des Polygons-Bereichs durchzuführen.Antworten:
Theoretisch sollten die von Ihnen durchgeführten Abfragen die Polygone zurückgeben, von denen Sie sagten, dass sie nicht zurückgegeben wurden. Das lässt mich vermuten, dass Sie möglicherweise auf Gleitkommafehlerprobleme stoßen, die SQL Server mit räumlichen Datentypen hat. Daher mein Kommentar zum Puffern des Begrenzungspolygons mit einem minimalen Betrag.
So etwas wie das Folgende sollte also die gewünschten Ergebnisse erzielen.
Hier ist ein kurzes Beispiel für das erwartete Verhalten einiger räumlicher Methoden.
Ergebnisse
quelle
Die Schnittpunktabfrage sollte folgendermaßen aussehen (vorausgesetzt, Sie möchten alle Datensätze von 'a' zurück):
Wenn Sie nur die Bereiche von a möchten, die b schneiden (dh a bis b abschneiden), fügen Sie den STIntersection hinzu
Aber das bringt dir noch nicht die Polygone, die innerhalb von b sind ...
Diese Art von Polygon-in-Polygon ist sehr gereizt mit den Grenzen und ihrer Übereinstimmung - um "innerhalb" zu sein, können die Grenzen von a nicht mit den Grenzen von b übereinstimmen - dasselbe gilt für "Enthält".
Wie viele Ihrer Polygone in a befinden sich nach diesen Definitionen tatsächlich innerhalb von b ...?
Möchten Sie also b puffern, bevor Sie Polygone in a auswählen, die sich darin befinden? Oder einen negativen Puffer auf a machen?
Ich bin mir nicht sicher, wie die genaue Antwort hier lautet ...
quelle