6

次の表を考えます。

table A (id, latitude, longitude)
table B (id, latitude, longitude)

A の各行を B の最も近い行に関連付ける効率的な T-SQL クエリを作成するにはどうすればよいですか?

ResultSet には、A のすべての行が含まれ、それらを B の 1 つの要素のみに関連付ける必要があります。私が探している形式は次のとおりです。

(A.id, B.id, distanceAB)

緯度と経度の 2 つのペアを指定して距離を計算する関数があります。order by ... limit 1and/orを使用して何かを試してみましrank() over (partition by ...) as rowCount ... where rowCount = 1たが、結果は実際には必要なものではないか、戻るのに時間がかかりすぎます。

何か不足していますか?

4

3 に答える 3

8

A のすべてのレコードを B のすべてのレコードと比較する必要があるという事実を回避する方法はありません。A と B の両方に多くのレコードが含まれている場合、明らかにスケーリングが不十分になります。

そうは言っても、これは正しい結果を返します:

SELECT aid, bid, distanceAB
FROM (
  SELECT aid, bid, distanceAB,
    dense_rank() over (partition by aid order by distanceAB) as n
  FROM (
    SELECT a.id as aid, B.id as bid,
      acos(sin(radians(A.lat)) * sin(radians(B.lat)) +
        cos(radians(A.lat)) * cos(radians(B.lat)) *
        cos(radians(A.lon - B.lon))) * 6372.8 as distanceAB
    FROM A cross join B
  ) C
) D
WHERE n = 1

セットが大きすぎない場合、これは妥当な時間で返されます。A に 3 か所、B に 130,000 か所ほどあるので、私のマシンでは約 1 秒かかります。1,000 レコードごとに約 40 秒かかります。私が言ったように、それはスケーリングが不十分です。

特定の状況下では、Sparky の回答が誤った結果を返す可能性があることに注意してください。A ロケーションが +40,+100 であるとします。+49,+109 よりも近い場合でも、+40,+111 は返されません。

于 2012-01-21T02:14:12.837 に答える
1

これは適切なパフォーマンスが得られるアプローチの 1 つですが、結果が得られない可能性があるという大きな注意点があります。

    select top 1 a.id,b.id,dbo.yourFunction() as DistanceAB
    from a 
    join b on b.latitude between a.latitude-10 and a.latitude+10 and
              b.longititude between a.longitude-10 and b.longittude+10
    order by 3

あなたが基本的に行っているのは、A の半径約 20 単位内にある任意の B 行を探し、それを関数で並べ替えて最も近いものを決定することです。必要に応じてユニットの半径を調整できます。正確ではありませんが、結果セットのサイズが縮小され、適切なパフォーマンス結果が得られるはずです。

于 2012-01-20T23:23:05.557 に答える
0

2 つのサブクエリを結合することで可能です。1 つ目は A 地点と B 地点の間のすべての距離を含み、2 つ目は A 地点からの B 地点の最小距離のみを含みます。

SELECT x.aid, x.bid, x.distance
FROM
(SELECT A.ID AS aid, 
        B.ID AS bid, 
        SQRT(A.Latitude * A.Latitude + B.Longitude * B.Longitude) AS Distance
     FROM LocationsA AS A 
     CROSS JOIN LocationsB AS B) x JOIN
(SELECT A.ID AS aid, 
        MIN(SQRT(A.Latitude * A.Latitude + B.Longitude * B.Longitude)) AS Distance
     FROM LocationsA AS A 
     CROSS JOIN LocationsB AS B
     GROUP BY A.ID) y ON x.aid = y.aid AND x.Distance = y.Distance
于 2012-01-20T23:43:47.707 に答える