Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Microsoft SQL bietet zwei räumliche Datentypen, die man über den mssql-python-Treiber verwenden kann. Wählen Sie den Typ basierend darauf, was Ihre Koordinaten repräsentieren:
| Typ | Beschreibung | Anwendungsfall |
|---|---|---|
geography |
Runderde-Koordinatensystem | GPS-Koordinaten, Karten, alles auf der Erdoberfläche. Die Entfernungen sind in Metern. SRID 4326 (WGS 84) ist Standard für GPS. |
geometry |
Flat-Plane-Koordinatensystem | Grundrisse, CAD-Zeichnungen, Spielwelten oder jedes kartesische Koordinatensystem. Die Entfernungen sind in den Einheiten deines Koordinatensystems angegeben. |
Räumliche Daten einfügen
Verwenden Sie Microsoft SQL-Konstruktorfunktionen wie geography::Point() oder übergeben Sie Well-Known Text (WKT)-Zeichenketten.
Geographiedaten (Punkte)
Fügen Sie geografische Punkte mit dem Punktkonstruktor mit Breite, Längengrad und SRID ein.
import mssql_python
connection_string = "Server=<server>.database.windows.net;Database=AdventureWorks2022;Authentication=ActiveDirectoryDefault;Encrypt=yes"
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
# Insert a geographic point (longitude, latitude)
# Note: Microsoft SQL uses (longitude, latitude) order
cursor.execute("CREATE TABLE #Locations (Name NVARCHAR(100), GeoLocation GEOGRAPHY)")
cursor.execute("""
INSERT INTO #Locations (Name, GeoLocation)
VALUES (%(name)s, geography::Point(%(lat)s, %(lon)s, 4326))
""", {"name": "Seattle", "lat": 47.6062, "lon": -122.3321})
conn.commit()
Geografie aus WKT (Well-Known Text)
Fügen Sie geografische Daten mit Well-Known Textformat ein, das Punkte, Linienstrings und Polygone unterstützt.
# Well-Known Text format
wkt_point = "POINT(-122.3321 47.6062)"
wkt_line = "LINESTRING(-122.3321 47.6062, -122.4194 37.7749)"
wkt_polygon = "POLYGON((-122.40 47.60, -122.30 47.60, -122.30 47.65, -122.40 47.65, -122.40 47.60))"
cursor.execute("DROP TABLE IF EXISTS #Locations")
cursor.execute("CREATE TABLE #Locations (Name NVARCHAR(100), GeoLocation GEOGRAPHY)")
cursor.execute("""
INSERT INTO #Locations (Name, GeoLocation)
VALUES (%(name)s, geography::STGeomFromText(%(wkt)s, 4326))
""", {"name": "Route", "wkt": wkt_line})
conn.commit()
Geometriedaten
Fügen Sie Flächengeometriedaten mit Punkten und Polygonen für CAD-Zeichnungen oder Grundrisse ein.
# Insert a geometry point (flat coordinate system)
cursor.execute("CREATE TABLE #FloorPlan (RoomName NVARCHAR(100), RoomShape GEOMETRY)")
cursor.execute("""
INSERT INTO #FloorPlan (RoomName, RoomShape)
VALUES (%(name)s, geometry::Point(%(x)s, %(y)s, 0))
""", {"name": "Office 101", "x": 50.0, "y": 100.0})
# Insert a geometry polygon
room_wkt = "POLYGON((0 0, 0 10, 20 10, 20 0, 0 0))"
cursor.execute("""
INSERT INTO #FloorPlan (RoomName, RoomShape)
VALUES (%(name)s, geometry::STGeomFromText(%(wkt)s, 0))
""", {"name": "Conference Room", "wkt": room_wkt})
conn.commit()
Abfrage räumlicher Daten
Verwenden Sie räumliche Methoden wie STAsText() und die Eigenschaften, Lat/Long um Koordinaten in einem lesbaren Format abzurufen.
Als Text abrufen
Räumliche Koordinaten zusammen mit Breiten- und Längengrad-Eigenschaften im Well-Known-Text-Format abrufen.
cursor.execute("""
SELECT
City,
SpatialLocation.STAsText() AS LocationWKT,
SpatialLocation.Lat AS Latitude,
SpatialLocation.Long AS Longitude
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
""")
for row in cursor.fetchall()[:5]:
print(f"{row.City}: {row.Latitude}, {row.Longitude}")
print(f" WKT: {row.LocationWKT}")
Abruf als GeoJSON
Microsoft SQL unterstützt die GeoJSON-Konvertierung. In SQL Server 2017+ können Sie String-Funktionen verwenden, um GeoJSON direkt zu bauen, oder in Python konvertieren, wie unten gezeigt:
cursor.execute("""
SELECT
City,
SpatialLocation.STAsText() AS WKT
FROM Person.Address
WHERE SpatialLocation IS NOT NULL AND City = %(city)s
""", {"city": "Seattle"})
for row in cursor:
print(f"{row.City}: {row.WKT}")
Finde nahegelegene Punkte
Finde alle Orte innerhalb eines angegebenen Abstands zu einem Referenzpunkt mithilfe von räumlichen Abstandsfunktionen.
# Find locations within 10 km of Seattle
cursor.execute("""
DECLARE @seattle geography = geography::Point(47.6062, -122.3321, 4326);
SELECT
City,
SpatialLocation.STDistance(@seattle) / 1000 AS DistanceKM
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
AND SpatialLocation.STDistance(@seattle) < 50000 -- 50 km in meters
ORDER BY SpatialLocation.STDistance(@seattle)
""")
for row in cursor.fetchall()[:5]:
print(f"{row.City}: {row.DistanceKM:.2f} km away")
Punkte innerhalb eines Polygons finden
Finden Sie alle Punkte, die sich mit einem geografischen Polygonbereich schneiden oder dort liegen.
# Find all addresses within a region
cursor.execute("""
DECLARE @region geography = geography::STPolyFromText(
'POLYGON((-122.5 47.5, -122.2 47.5, -122.2 47.7, -122.5 47.7, -122.5 47.5))',
4326
);
SELECT City, SpatialLocation.STAsText() AS Location
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
AND @region.STIntersects(SpatialLocation) = 1
""")
Entfernungen berechnen
Die Methode von STDistance() Microsoft SQL liefert Entfernungen in Metern für geografische Typen zurück.
Abstand zwischen zwei Punkten
Erstellen Sie eine Hilfsfunktion, um die Entfernung in Kilometern zwischen zwei geografischen Punkten zu berechnen.
def get_distance_km(cursor, point1: tuple, point2: tuple) -> float:
"""Calculate distance between two points in kilometers."""
cursor.execute("""
DECLARE @point1 geography = geography::Point(%(lat1)s, %(lon1)s, 4326);
DECLARE @point2 geography = geography::Point(%(lat2)s, %(lon2)s, 4326);
SELECT @point1.STDistance(@point2) / 1000 AS DistanceKM;
""", {
"lat1": point1[0], "lon1": point1[1],
"lat2": point2[0], "lon2": point2[1]
})
return cursor.fetchval()
# Seattle to San Francisco
distance = get_distance_km(cursor, (47.6062, -122.3321), (37.7749, -122.4194))
print(f"Distance: {distance:.2f} km")
Fläche berechnen
Berechnen Sie die Fläche einer geografischen Region in Quadratkilometern.
cursor.execute("""
DECLARE @region geography = geography::STPolyFromText(
'POLYGON((-122.5 47.5, -122.2 47.5, -122.2 47.7, -122.5 47.7, -122.5 47.5))',
4326
);
SELECT
'Seattle Region' AS Name,
@region.STArea() / 1000000 AS AreaSqKm
""")
row = cursor.fetchone()
print(f"{row.Name}: {row.AreaSqKm:.2f} sq km")
Räumliche Operationen
Microsoft SQL unterstützt Set-Operationen auf räumlichen Objekten, einschließlich Union, Intersection und Buffer.
Vereinigung der Formen
Kombinieren Sie zwei geografische Polygone zu einer einzigen Form und berechnen Sie die Gesamtfläche.
cursor.execute("""
DECLARE @parcel1 geography = geography::STPolyFromText(
'POLYGON((-122.35 47.60, -122.33 47.60, -122.33 47.62, -122.35 47.62, -122.35 47.60))',
4326
);
DECLARE @parcel2 geography = geography::STPolyFromText(
'POLYGON((-122.34 47.61, -122.32 47.61, -122.32 47.63, -122.34 47.63, -122.34 47.61))',
4326
);
DECLARE @combined geography = @parcel1.STUnion(@parcel2);
SELECT @combined.STAsText() AS CombinedWKT,
@combined.STArea() / 1000000 AS TotalAreaKM
""")
row = cursor.fetchone()
print(f"Combined area: {row.TotalAreaKM:.2f} sq km")
Schnittpunkt
Ermitteln Sie den Überlappungsbereich, in dem sich zwei geografische Regionen überschneiden.
polygon1_wkt = "POLYGON((-122.35 47.60, -122.33 47.60, -122.33 47.62, -122.35 47.62, -122.35 47.60))"
polygon2_wkt = "POLYGON((-122.34 47.61, -122.32 47.61, -122.32 47.63, -122.34 47.63, -122.34 47.61))"
cursor.execute("""
DECLARE @region1 geography = geography::STPolyFromText(%(wkt1)s, 4326);
DECLARE @region2 geography = geography::STPolyFromText(%(wkt2)s, 4326);
SELECT
@region1.STIntersection(@region2).STAsText() AS IntersectionWKT,
@region1.STIntersection(@region2).STArea() / 1000000 AS AreaKM
""", {"wkt1": polygon1_wkt, "wkt2": polygon2_wkt})
Puffer (Fläche erweitern)
Erstelle eine Pufferzone um einen geografischen Punkt und finde alle Standorte innerhalb des Pufferradius.
# Find all addresses within 5km buffer of a point
cursor.execute("""
DECLARE @center geography = geography::Point(47.6062, -122.3321, 4326);
DECLARE @buffer geography = @center.STBuffer(5000); -- 5 km buffer
SELECT City
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
AND @buffer.STIntersects(SpatialLocation) = 1
""")
Python-Integration
Rufen Sie WKT-Strings aus Microsoft SQL ab und parsen Sie sie mit der Shapely-Bibliothek für die clientseitige Geometrieverarbeitung.
Mit der Shapely-Bibliothek
Installiere, indem du pip install shapely ausführst.
from shapely import wkt
from shapely.geometry import Point, Polygon
# Retrieve spatial data from Person.Address
cursor.execute("""
SELECT City, SpatialLocation.STAsText() AS WKT
FROM Person.Address
WHERE SpatialLocation IS NOT NULL AND City IN ('Seattle', 'Redmond')
""")
for row in cursor:
# Parse WKT into Shapely geometry
geom = wkt.loads(row.WKT)
if isinstance(geom, Point):
print(f"{row.City}: Point at ({geom.x}, {geom.y})")
elif isinstance(geom, Polygon):
print(f"{row.City}: Polygon with area {geom.area}")
Räumliche Daten mit Shapely erstellen
Erstellen Sie geometrische Objekte mit der Shapely-Bibliothek und konvertieren Sie sie in das WKT-Format für die Einfügung in Microsoft SQL.
from shapely.geometry import Point, Polygon, LineString
from shapely import wkt
# Create geometries in Python
seattle = Point(-122.3321, 47.6062)
seattle_wkt = wkt.dumps(seattle)
route = LineString([(-122.3321, 47.6062), (-122.4194, 37.7749)])
route_wkt = wkt.dumps(route)
# Insert into a temp table
cursor.execute("CREATE TABLE #Routes (Name NVARCHAR(100), Path NVARCHAR(MAX))")
cursor.execute("""
INSERT INTO #Routes (Name, Path)
VALUES (%(name)s, %(wkt)s)
""", {"name": "Seattle to SF", "wkt": route_wkt})
cursor.execute("SELECT Name, Path FROM #Routes")
row = cursor.fetchone()
print(f"{row.Name}: {row.Path[:40]}...")
Konvertiere zu GeoJSON
Konvertiere räumliche Daten vom WKT-Format in GeoJSON für webbasierte Anwendungen und Kartierungsdienste.
import json
from shapely import wkt
from shapely.geometry import mapping
cursor.execute("""
SELECT City, SpatialLocation.STAsText() AS WKT
FROM Person.Address
WHERE SpatialLocation IS NOT NULL AND City = 'Seattle'
""")
row = cursor.fetchone()
geom = wkt.loads(row.WKT)
geojson = {
"type": "Feature",
"properties": {"name": row.City},
"geometry": mapping(geom)
}
print(json.dumps(geojson, indent=2))
GeoDataFrame-Integration
Laden Sie räumliche Daten von Microsoft SQL in einen GeoPandas GeoDataFrame für fortgeschrittene geospatiale Analysen.
import geopandas as gpd
from shapely import wkt
import pandas as pd
cursor.execute("""
SELECT AddressID, City, SpatialLocation.STAsText() AS WKT
FROM Person.Address
WHERE SpatialLocation IS NOT NULL AND City = 'Seattle'
""")
# Build DataFrame
rows = cursor.fetchall()
df = pd.DataFrame(
[(r.AddressID, r.City, r.WKT) for r in rows],
columns=['id', 'city', 'wkt']
)
# Convert to GeoDataFrame
df['geometry'] = df['wkt'].apply(wkt.loads)
gdf = gpd.GeoDataFrame(df, geometry='geometry', crs="EPSG:4326")
# Now use GeoPandas operations
print(gdf.head())
Räumliche Indizes
Erstellen Sie räumliche Indizes in Microsoft SQL, um Abfragen auf großen räumlichen Datensätzen zu beschleunigen.
-- Geography index on Person.Address
CREATE SPATIAL INDEX SIX_Address_SpatialLocation
ON Person.Address(SpatialLocation)
USING GEOGRAPHY_GRID
WITH (
GRIDS = (LEVEL_1 = MEDIUM, LEVEL_2 = MEDIUM, LEVEL_3 = MEDIUM, LEVEL_4 = MEDIUM),
CELLS_PER_OBJECT = 16
);
-- Geometry index (example with custom table)
CREATE SPATIAL INDEX SIX_FloorPlan_RoomShape
ON dbo.FloorPlan(RoomShape)
USING GEOMETRY_GRID
WITH (
BOUNDING_BOX = (0, 0, 1000, 1000),
GRIDS = (LEVEL_1 = HIGH, LEVEL_2 = HIGH, LEVEL_3 = HIGH, LEVEL_4 = HIGH)
);
Leistungstipps
Wenden Sie diese Techniken an, um räumliche Abfragen in großem Maßstab effizient zu halten.
Verwenden Sie räumliche Indexhinweise
Verwenden Sie räumliche Indizes, um Abfragen auf großen räumlichen Datensätzen zu beschleunigen.
cursor.execute("""
DECLARE @region geography = geography::STPolyFromText(
'POLYGON((-122.5 47.5, -122.2 47.5, -122.2 47.7, -122.5 47.7, -122.5 47.5))',
4326
);
SELECT City
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
AND SpatialLocation.STIntersects(@region) = 1
""")
Erst filtern, dann berechnen
Optimieren Sie räumliche Abfragen, indem Sie zunächst einen schnellen Bounding-Box-Filter anwenden und anschließend genaue Distanzberechnungen durchführen.
# Approximate filter with bounding box, then precise calculation
cursor.execute("""
DECLARE @center geography = geography::Point(47.6062, -122.3321, 4326);
SELECT City, SpatialLocation.STDistance(@center) AS Distance
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
AND SpatialLocation.Filter(@center.STBuffer(10000)) = 1 -- Fast bounding box filter
AND SpatialLocation.STDistance(@center) < 10000 -- Precise distance check
ORDER BY Distance
""")
Reduziere die Präzision bei der Darstellung
Vereinfachen Sie räumliche Geometrien für die Darstellung, indem Sie die Koordinatengenauigkeit reduzieren.
cursor.execute("""
SELECT
City,
SpatialLocation.Reduce(100).STAsText() AS SimplifiedWKT -- 100 meter tolerance
FROM Person.Address
WHERE SpatialLocation IS NOT NULL AND City = 'Seattle'
""")
Koordinatenreferenzsysteme
Das SRID bestimmt das Koordinatensystem und beeinflusst, wie Microsoft SQL Entfernungen und Flächen berechnet.
Häufige SRID-Werte
Das SRID (Spatial Reference Identifier) definiert das Koordinatensystem für Ihre Daten. Die Verwendung des falschen SRID führt zu falschen Entfernungs- und Flächenberechnungen.
| SRID | Name | Anwendungsfall |
|---|---|---|
| 4,326 | WGS 84 | GPS-Koordinaten, Webkartierung |
| 4269 | NAD 83 | Nordamerikanische Vermessungen |
| 0 | Kein SRID | Flache Geometrie, lokale Koordinaten |
Konvertieren zwischen SRIDs
Räumliche Daten abrufen und deren SRID überprüfen, um das Koordinatensystem zu überprüfen.
cursor.execute("""
-- Geography is always round-earth, but SRID defines datum
SELECT SpatialLocation.STAsText() AS WKT,
SpatialLocation.STSrid AS SRID
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
""")
Bewährte Methoden
Wenden Sie diese Richtlinien an, um mit räumlichen Daten korrekt und effizient zu arbeiten.
Geometrie validieren
Überprüfen Sie räumliche Daten auf Gültigkeit und identifizieren Sie geometrische Probleme vor der Verarbeitung.
cursor.execute("""
SELECT
City,
SpatialLocation.STIsValid() AS IsValid,
SpatialLocation.IsValidDetailed() AS InvalidReason
FROM Person.Address
WHERE SpatialLocation IS NOT NULL
AND SpatialLocation.STIsValid() = 0
""")
for row in cursor:
print(f"Invalid: {row.City} - {row.InvalidReason}")
Geometrie validieren
Verwenden Sie die Methode MakeValid() , um ungültige geometrische Formen automatisch zu korrigieren.
# Example with a temp table
cursor.execute("""
CREATE TABLE #SpatialFix (Name NVARCHAR(100), GeoLocation GEOGRAPHY);
INSERT INTO #SpatialFix VALUES ('Test', geography::STGeomFromText('POLYGON((0 0, 0 1, 1 0, 0 0))', 4326));
UPDATE #SpatialFix
SET GeoLocation = GeoLocation.MakeValid()
WHERE GeoLocation.STIsValid() = 0
""")
Wählen Sie den richtigen Typ
Die Wahl zwischen geography und geometry bestimmt, wie Microsoft SQL Entfernungen und Flächen berechnet:
- Geografie: Reale Orte (GPS-Punkte), Berechnungen der Erdoberfläche, Entfernungen in Metern.
- Geometrie: Flache Flächen (Grundrisse, CAD), kartesische Koordinatensysteme oder wenn SRID keine Rolle spielt.