sql >> Database teknologi >  >> RDS >> Sqlserver

Få den nærmeste længde- og breddegrad fra MSSQL-databasetabellen?

Lad os se på et simpelt eksempel på brug af STDistance funktion i SQL Server 2008 (og senere).

Jeg vil fortælle SQL Server, at jeg er i London, og jeg vil gerne se, hvor langt væk hvert af mine kontorer er. Her er de resultater, som jeg vil have SQL Server til at give mig:

Først skal vi bruge nogle eksempeldata. Vi opretter en tabel, der indeholder nogle få placeringer af Microsoft-kontorer, og vi gemmer deres længde- og breddegradsværdier i en geography felt.

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())

Hvis vi nu var i London. Sådan laver du en geography værdi ud af Londons længde- og breddegradsværdier:

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) + ')';

Og lad os endelig se, hvor langt hvert af vores kontorer er.

SELECT [Office_Name], 
       cast([Office_Location].STDistance(@g) / 1609.344 as numeric(10, 1)) as 'Distance (in miles)' 
FROM [Offices]
ORDER BY 2 ASC

Og dette giver os de resultater, vi håbede på.

Selvfølgelig kunne du smide en TOP(1) ind hvis du bare ville se den nærmeste kontor.

Fedt, hej?

Der er kun en hage. Når du har meget geography punkter at sammenligne med, ydeevnen er ikke genial, selvom du tilføjer et SPATIAL INDEX på det databasefelt.

Jeg testede et punkt mod en tabel med 330.000 geography point. Ved at bruge koden vist her fandt den det nærmeste punkt på ca. 8 sekunder .

Da jeg ændrede min tabel til at gemme længde- og breddegradsværdierne og brugte [dbo].[fnCalcDistanceMiles] funktion fra denne StackOverflow-artikel, fandt den det nærmeste punkt på ca. 3 sekunder .

Dog...

Alle eksemplerne på "afstand mellem to punkter", jeg fandt på internettet, brugte enten SQL Server STDistance funktion eller matematiske formler, der involverer de (CPU-intensive) cos-, sin- og tan-funktioner.

En hurtigere løsning var at rejse tilbage i tiden til gymnasiet, og huske hvordan Pythagoras beregnede afstanden mellem to punkter.

Antag, at vi ville vide afstanden mellem London og Paris.

Og her er min 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

Husk nu, at denne funktion ikke returnerer en værdi i miles, kilometer osv... den sammenligner blot længde- og breddegradsværdierne. Og Pythagoras er beregnet til at blive brugt i 2D, og ​​ikke sammenligne punkter på en rund planet!

I mine test fandt den dog det nærmeste punkt inden for 1 sekund , og gav de samme resultater som ved brug af SQL Servers STDistance funktion.

Så du er velkommen til at bruge denne funktion til at sammenligne relative afstande , men brug ikke denne funktion, hvis du har brug for selve afstanden.

Håber alt dette hjælper.



  1. hvordan kan man sammenkæde mere end to kolonner i plsql-udvikler?

  2. Sådan får du alder i år, måneder og dage ved at bruge Oracle

  3. Sådan får du kalenderkvartal fra en dato i TSQL

  4. SSRS-rapportdefinitionen er nyere end Server