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
を使用した場合と同じ結果が得られました 機能。
したがって、この関数を使用して、相対距離を比較してください。 、ただし、実際の距離自体が必要な場合は、この関数を使用しないでください。
これがすべてお役に立てば幸いです。