sql >> データベース >  >> RDS >> Sqlserver

MSSQLデータベーステーブルから最も近い経度と緯度を取得しますか?

    STDistanceを使用する簡単な例を見てみましょう。 SQL Server 2008(およびそれ以降)で機能します。

    SQL Serverに、ロンドンにいることを伝えます。各オフィスがどれだけ離れているかを確認したいと思います。 SQLServerに提供してほしい結果は次のとおりです。

    まず、いくつかのサンプルデータが必要です。 Microsoftのオフィスのいくつかの場所を含むテーブルを作成し、それらの経度と緯度の値をgeographyに保存します。 フィールド。

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

    今、私たちがロンドンにいたとしましょう。 geographyを作成する方法は次のとおりです ロンドンの経度と緯度の値のうちの値:

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

    そして最後に、各オフィスの距離を見てみましょう。

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

    そして、これは私たちが望んでいた結果を私たちに与えます。

    明らかに、TOP(1)を挿入することができます 最も近いを見たいだけの場合 オフィス。

    かっこいい、ねえ?

    たった1つの障害があります。 geographyがたくさんある場合 比較すべき点は、そのデータベースフィールドに空間インデックスを追加したとしても、パフォーマンスは素晴らしいものではありません。

    330,000のgeographyのテーブルに対してポイントをテストしました ポイント。ここに示すコードを使用すると、約8秒で最も近いポイントが見つかりました 。

    経度と緯度の値を格納するようにテーブルを変更し、[dbo].[fnCalcDistanceMiles]を使用したとき このStackOverflowの記事の関数では、約3秒で最も近いポイントが見つかりました 。

    しかし...

    インターネットで見つけた「2点間の距離」のサンプルはすべて、SQLServerのSTDistanceを使用していました。 関数、または(CPUを集中的に使用する)cos、sin、およびtan関数を含む数式。

    より速い解決策は、高校に戻って、ピタゴラスが2点間の距離をどのように計算したかを覚えておくことでした。

    ロンドンとパリの間の距離を知りたいとしましょう。

    これが私のSQLServer関数です:

    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
    

    さて、この関数はマイルやキロメートルなどの値を返さないことを覚えておいてください...それは単に経度と緯度の値を比較しているだけです。また、ピタゴラスは2Dで使用することを目的としており、丸い惑星上の点を比較することはできません!

    ただし、私のテストでは、1秒以内に最も近いポイントが見つかりました 、SQLServerのSTDistanceを使用した場合と同じ結果が得られました 機能。

    したがって、この関数を使用して、相対距離を比較してください。 、ただし、実際の距離自体が必要な場合は、この関数を使用しないでください。

    これがすべてお役に立てば幸いです。



    1. Postgresは最もクールなデータベースです–理由#2:ライセンス

    2. pgAdmin IIIクエリ結果が短縮されるのはなぜですか?

    3. MySQLでユーザーを作成する方法

    4. 致命的なエラー:キャッチされない例外'mysqli_sql_exception'とメッセージ'クエリ/プリペアドステートメントでインデックスが使用されていません'