6

次のデータが与えられた場合、それは可能であり、そうであれば、最初のテーブルの場所「Shurdington」が2番目のテーブルのいずれかの場所の指定された半径内に含まれるかどうかを判断する最も効率的な方法です。

GeoData列は「geography」タイプであるため、SQL Serverの空間機能を使用することは、緯度と経度を使用することと同様にオプションです。

Location      GeoData       Latitude    Longitude
===========================================================
Shurdington   XXXXXXXXXX    51.8677979  -2.113189

ID  Location            GeoData     Latitude    Longitude   Radius
==============================================================================
1000    Gloucester      XXXXXXXXXX  51.8907127  -2.274598   10
1001    Leafield        XXXXXXXXXX  51.8360519  -1.537438   10
1002    Wotherton       XXXXXXXXXX  52.5975151  -3.061798   5
1004    Nether Langwith XXXXXXXXXX  53.2275276  -1.212108   20
1005    Bromley         XXXXXXXXXX  51.4152069  0.0292294   10

どんな援助も大いに感謝されます。

4

3 に答える 3

9

データの作成

CREATE TABLE #Data (
    Id int,
    Location nvarchar(50),
    Latitude decimal(10,5),
    Longitude decimal(10,5),
    Radius int
)

INSERT #Data (Id,Location,Latitude,Longitude,Radius) VALUES 
(1000,'Gloucester', 51.8907127 ,-2.274598  , 20), -- Increased to 20
(1001,'Leafield', 51.8360519 , -1.537438  , 10),
(1002,'Wotherton', 52.5975151,  -3.061798  , 5),
(1004,'Nether Langwith', 53.2275276 , -1.212108  , 20),
(1005,'Bromley', 51.4152069 , 0.0292294  , 10)

テスト

興味のあるポイントを次のように宣言しますPOINT

DECLARE @p GEOGRAPHY = GEOGRAPHY::STGeomFromText('POINT(-2.113189 51.8677979)', 4326);

それが別の点の半径内にあるかどうかを確認するには:

-- First create a Point.
DECLARE @point GEOGRAPHY = GEOGRAPHY::STGeomFromText('POINT(-2.27460 51.89071)', 4326);
-- Buffer the point (meters) and check if the 1st point intersects
SELECT @point.STBuffer(50000).STIntersects(@p)

すべてを1つのクエリにまとめます。

select  *,
        GEOGRAPHY::STGeomFromText('POINT('+ 
            convert(nvarchar(20), Longitude)+' '+
            convert( nvarchar(20), Latitude)+')', 4326)
        .STBuffer(Radius * 1000).STIntersects(@p) as [Intersects]
from    #Data  

与える:

Id      Location        Latitude    Longitude   Radius  Intersects
1000    Gloucester      51.89071    -2.27460    20      1
1001    Leafield        51.83605    -1.53744    10      0
1002    Wotherton       52.59752    -3.06180    5       0
1004    Nether Langwith 53.22753    -1.21211    20      0
1005    Bromley         51.41521    0.02923     10      0

Re:効率。いくつかの正しいインデックス付けを使用すると、SQLの空間インデックスは非常に高速になる可能性があります

于 2013-02-04T10:37:29.117 に答える
1

2点間の距離を計算し、この距離を指定された半径と比較します。

短距離の計算には、Wikipedia-地理的距離-平面に投影された球体地球の式を使用できます。これは、「非常に高速で、短距離でもかなり正確な結果を生成する」と主張しています。

式によると、緯度と経度の差と平均緯度が必要です

with geo as (select g1.id, g1.latitude as lat1, g1.longitude as long1, g1.radius,
                    g2.latitude as lat2, g2.longitude as long2
             from geography g1
             join geography g2 on g2.location = 'shurdington'
                               and g1.location <> 'shurdington')
     base as (select id,
                     (radians(lat1) - radians(lat2)) as dlat,
                     (radians(long1) - radians(long2)) as dlong,
                     (radians(lat1) + radians(lat2)) / 2 as mlat, radius
              from geo)
     dist as (select id,
                     6371.009 * sqrt(square(dlat) + square(cos(mlat) * dlong)) as distance,
                     radius
              from base)
select id, distance
from dist
where distance <= radius

with select計算を「読みやすく」保つための中間ステップとしてsを使用しました。

于 2013-02-04T10:43:27.653 に答える
1

自分で計算したい場合は、ピタゴラスに基づく正距円筒図法を使用できます。式は次のとおりです。

var x =(lon2-lon1)* Math.cos((lat1 + lat2)/ 2); var y =(lat2-lat1); var d = Math.sqrt(x * x + y * y)* R;

SQLの観点から、これにより、半径内の1番目のエントリを含む2番目のテーブルの場所が得られます。

SELECT *
FROM Table2 t2
WHERE EXISTS (
 SELECT 1 FROM Table1 t1
 WHERE 
  ABS (
  SQRT (
    (SQUARE((RADIANS(t2.longitude) - RADIANS(t1.longitude)) * COS((RADIANS(t2.Latitude) + RADIANS(t1.Latitude))/2))) +
    (SQUARE(RADIANS(t1.Latitude) - RADIANS(t2.Latitude)))
    ) * 6371 --Earth radius in km, use 3959 for miles
    )
    <= t2.Radius
)

これは利用可能な最も正確な方法ではありませんが、おそらく十分であることに注意してください。あなたが世界中に広がる距離を見ているなら、あなたはグーグルの「半正矢関数」の公式を望むかもしれません。

これをPaddyのソリューションと比較して、それらがどの程度一致し、どれが最高のパフォーマンスを発揮するかを確認することは価値があるかもしれません。

于 2013-02-04T10:43:32.093 に答える