Podívejme se na jednoduchý příklad použití STDistance
funkce v SQL Server 2008 (a novějších).
Řeknu SQL Serveru, že jsem v Londýně, a chci vidět, jak daleko jsou moje kanceláře. Zde jsou výsledky, které mi má SQL Server poskytnout:
Nejprve budeme potřebovat nějaká ukázková data. Vytvoříme tabulku obsahující několik umístění kanceláří společnosti Microsoft a jejich hodnoty zeměpisné délky a šířky uložíme do 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())
Předpokládejme, že jsme byli v Londýně. Zde je návod, jak vytvořit geography
hodnota mimo londýnské hodnoty zeměpisné délky a šířky:
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) + ')';
A nakonec se podívejme, jak daleko jsou naše kanceláře.
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 nám dává výsledky, ve které jsme doufali.
Je zřejmé, že můžete vložit TOP(1)
pokud jste jen chtěli vidět nejbližší kancelář.
Super, hej?
Je tu jen jeden háček. Když máte hodně geography
body k porovnání, výkon není oslnivý, i když do tohoto databázového pole přidáte SPATIAL INDEX.
Testoval jsem bod proti tabulce 330 000 geography
body. Pomocí zde zobrazeného kódu našel nejbližší bod za přibližně 8 sekund .
Když jsem upravil svou tabulku tak, aby ukládala hodnoty zeměpisné délky a šířky, a použil jsem [dbo].[fnCalcDistanceMiles]
funkce z tohoto článku StackOverflow nalezla nejbližší bod přibližně za 3 sekundy .
Nicméně...
Všechny ukázky "vzdálenosti mezi dvěma body", které jsem našel na internetu, buď používaly SQL Server STDistance
nebo matematické vzorce zahrnující funkce cos, sin a tan (intenzivní na CPU).
Rychlejším řešením bylo vrátit se v čase na střední školu a zapamatovat si, jak Pythagoras vypočítal vzdálenost mezi dvěma body.
Předpokládejme, že bychom chtěli znát vzdálenost mezi Londýnem a Paříží.
A tady je moje funkce 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
Pamatujte, že tato funkce nevrací hodnotu v mílích, kilometrech atd., pouze porovnává hodnoty zeměpisné délky a šířky. A Pythagoras je určen k použití ve 2D a ne k porovnávání bodů na kulaté planetě!
V mých testech však našel nejbližší bod do 1 sekundy a přineslo stejné výsledky jako při použití STDistance
SQL Serveru funkce.
Takže neváhejte použít tuto funkci pro porovnání relativních vzdáleností , ale tuto funkci nepoužívejte, pokud potřebujete samotnou skutečnou vzdálenost.
Doufám, že to všechno pomůže.