Sehen wir uns ein einfaches Beispiel für die Verwendung von STDistance
an Funktion in SQL Server 2008 (und höher).
Ich werde SQL Server mitteilen, dass ich in London bin, und ich möchte sehen, wie weit meine Büros entfernt sind. Hier sind die Ergebnisse, die SQL Server mir geben soll:
Zunächst benötigen wir einige Beispieldaten. Wir erstellen eine Tabelle mit einigen Standorten von Microsoft-Büros und speichern ihre Längen- und Breitengrade in einer geography
Feld.
CREATE TABLE [Offices] (
[Office_Id] [int] IDENTITY(1, 1) NOT NULL,
[Office_Name] [nvarchar](200) NOT NULL,
[Office_Location] [geography] NOT NULL,
[Update_By] nvarchar(30) NULL,
[Update_Time] [datetime]
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Zurich', 'POINT(8.590847 47.408860 )', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft San Francisco', 'POINT(-122.403697 37.792062 )', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Paris', 'POINT(2.265509 48.833946)', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Sydney', 'POINT(151.138378 -33.796572)', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Dubai', 'POINT(55.286282 25.228850)', 'mike', GetDate())
Angenommen, wir wären in London. So erstellen Sie eine geography
Wert aus Londons Längen- und Breitengradwerten:
DECLARE
@latitude numeric(12, 7),
@longitude numeric(12, 7)
SET @latitude = 51.507351
SET @longitude = -0.127758
DECLARE @g geography = 'POINT(' + cast(@longitude as nvarchar) + ' ' + cast(@latitude as nvarchar) + ')';
Und schließlich sehen wir uns an, wie weit jedes unserer Büros entfernt ist.
SELECT [Office_Name],
cast([Office_Location].STDistance(@g) / 1609.344 as numeric(10, 1)) as 'Distance (in miles)'
FROM [Offices]
ORDER BY 2 ASC
Und das liefert uns die erhofften Ergebnisse.
Offensichtlich könntest du ein TOP(1)
hineinschlüpfen wenn Sie nur die Nächste sehen wollten Büro.
Cool, hallo ?
Es gibt nur einen Haken. Wenn Sie viel geography
haben Vergleichspunkte, die Leistung ist nicht brillant, selbst wenn Sie diesem Datenbankfeld einen RÄUMLICHEN INDEX hinzufügen.
Ich habe einen Punkt gegen eine Tabelle mit 330.000 geography
getestet Punkte. Mit dem hier gezeigten Code wurde der nächstgelegene Punkt in etwa 8 Sekunden gefunden .
Als ich meine Tabelle geändert habe, um die Längen- und Breitengrade zu speichern, und den [dbo].[fnCalcDistanceMiles]
verwendet habe Funktion aus diesem StackOverflow-Artikel hat sie den nächstgelegenen Punkt in etwa 3 Sekunden gefunden .
Allerdings...
Alle Beispiele für "Entfernung zwischen zwei Punkten", die ich im Internet gefunden habe, verwendeten entweder den SQL Server STDistance
Funktion oder mathematische Formeln mit den (CPU-intensiven) cos-, sin- und tan-Funktionen.
Eine schnellere Lösung wäre, in der Zeit zurück zur High School zu reisen und sich daran zu erinnern, wie Pythagoras die Entfernung zwischen zwei Punkten berechnet hat.
Angenommen, wir wollten die Entfernung zwischen London und Paris wissen.
Und hier ist meine SQL Server-Funktion:
CREATE FUNCTION [dbo].[uf_CalculateDistance] (@Lat1 decimal(8,4), @Long1 decimal(8,4), @Lat2 decimal(8,4), @Long2 decimal(8,4))
RETURNS decimal (8,4) AS
BEGIN
DECLARE @d decimal(28,10)
SET @d = sqrt(square(@[email protected]) + square(@[email protected]))
RETURN @d
END
Denken Sie daran, dass diese Funktion keinen Wert in Meilen, Kilometern usw. zurückgibt. Sie vergleicht lediglich die Längen- und Breitengrade. Und Pythagoras soll in 2D verwendet werden und nicht zum Vergleichen von Punkten auf einem runden Planeten !
In meinen Tests fand es jedoch den nächstgelegenen Punkt innerhalb von 1 Sekunde , und erzeugte die gleichen Ergebnisse wie die Verwendung von STDistance
von SQL Server Funktion.
Verwenden Sie diese Funktion also gerne zum Vergleichen von relativen Entfernungen , aber verwenden Sie diese Funktion nicht, wenn Sie die tatsächliche Entfernung selbst benötigen.
Hoffe das alles hilft.