Spójrzmy na prosty przykład użycia STDistance
funkcja w SQL Server 2008 (i nowszych).
Powiem SQL Server, że jestem w Londynie i chcę zobaczyć, jak daleko są moje biura. Oto wyniki, które chcę uzyskać w programie SQL Server:
Najpierw potrzebujemy przykładowych danych. Utworzymy tabelę zawierającą kilka lokalizacji biur Microsoft i będziemy przechowywać ich wartości długości i szerokości geograficznej w geography
pole.
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())
Przypuśćmy, że jesteśmy w Londynie. Oto jak zrobić geography
wartość poza wartościami długości i szerokości geograficznej Londynu:
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) + ')';
I na koniec zobaczmy, jak daleko znajduje się każde z naszych biur.
SELECT [Office_Name],
cast([Office_Location].STDistance(@g) / 1609.344 as numeric(10, 1)) as 'Distance (in miles)'
FROM [Offices]
ORDER BY 2 ASC
A to daje nam wyniki, na które liczyliśmy.
Oczywiście możesz wsunąć TOP(1)
jeśli chcesz tylko zobaczyć najbliższe biuro.
Fajnie, hej?
Jest tylko jeden szkopuł. Gdy masz dużo geography
punktów do porównania, wydajność nie jest genialna, nawet jeśli dodasz INDEKS PRZESTRZENNY do tego pola bazy danych.
Przetestowałem punkt z tabelą 330 000 geography
zwrotnica. Używając pokazanego tutaj kodu, znalazł najbliższy punkt w około 8 sekund .
Kiedy zmodyfikowałem moją tabelę, aby przechowywać wartości długości i szerokości geograficznej, i użyłem [dbo].[fnCalcDistanceMiles]
funkcji z tego artykułu StackOverflow, znalazł najbliższy punkt w około 3 sekundy .
Jednak...
Wszystkie próbki "odległości między dwoma punktami", które znalazłem w Internecie, używały SQL Server STDistance
funkcja lub wzory matematyczne obejmujące (intensywnie wykorzystujące procesor) funkcje cos, sin i tan.
Szybszym rozwiązaniem było cofnięcie się w czasie do liceum i zapamiętanie, jak Pitagoras obliczył odległość między dwoma punktami.
Przypuśćmy, że chcielibyśmy poznać odległość między Londynem a Paryżem.
A oto moja funkcja SQL Server:
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
Teraz pamiętaj, że ta funkcja nie zwraca wartości w milach, kilometrach itp... po prostu porównuje wartości długości i szerokości geograficznej. A Pitagoras ma być używany w 2D, a nie do porównywania punktów na okrągłej planecie!
Jednak w moich testach znalazł najbliższy punkt w ciągu 1 sekundy , i dał takie same wyniki, jak przy użyciu STDistance
programu SQL Server funkcja.
Możesz więc użyć tej funkcji do porównywania odległości względnych , ale nie używaj tej funkcji, jeśli potrzebujesz samej rzeczywistej odległości.
Mam nadzieję, że to wszystko pomoże.