2011-01-27 8 views
5

gps-point間の距離を計算して、最初の最後の点と最後の点との間の完全な距離を求めたいとします。T-SQL早送りカーソル対foreach

私の質問です:何が速いですか? FastForward カーソルで のStoredProcedureを使用してforeachの または経由のDataTableにすべての行をロードし、 C#.NETで、それを計算するのに

  • Caluclateそれは、SQL-Server上。

私は、約400,000行のアマウトを話します。あなたは、SQL Server 2008を使用している場合

+1

サーバー**で**を計算するのが最も速いですが**カーソルなしで** ..... –

+0

@marc_s:カーソルなしで各行に距離を追加する方法はありますか? – mabstrei

+0

私の反応を見てください - 私たちには詳細がたくさんありませんので、私は非常に一般化されたアイデアしか提供できません.... –

答えて

4

私は間違いなくサーバー上でこれをやろうとします.1つの数値を計算するために400,000行をドラッグしないようにしてください。

また、可能であればにカーソルが表示されないようにしています。カーソルはSQL Serverの悪夢であり、絶対に避けてください。

あなたのケースでは、詳細なテーブル構造を知らずに、あなたは間違いなくそうすることができます。最初の要素から始まり、総距離が0.0の再帰的CTE(Common Table Expression)を計算し、他のすべてのウェイポイントを再帰的に合計し、ポイント(x + 1)とポイントxの間の距離を計算し、前の合計。

最後に、すべてのウェイポイント、任意の2つのウェイポイント間のすべての距離、および旅程全体の合計距離を示すCTEが必要です。

CTEのようなものであろうと:

;WITH Waypoints AS 
(
    -- anchor your query 
    SELECT 
     WaypointID, PrevWaypointID, Long, Lat, 0.0 as Distance, 0.0 as SumOfDistance 
    FROM 
     dbo.Waypoint 
    WHERE 
     PrevWaypointID IS NULL -- or some other condition 

    UNION -- recurse 

    SELECT 
     WaypointID, Long, Lat, 
     dbo.GetDistanceBetween(wp.WaypointID, pts.WaypointID), -- distance 
     pts.SumOfDistance + dbo.GetDistanceBetween(wp.WaypointID, pts.WaypointID) -- sum 
    FROM 
     dbo.Waypoint wp 
    INNER JOIN 
     Waypoints pts ON wp.PrevWaypointID = pts.WaypointID   
    WHERE 
     (some condition; ID = 1 or PreviousWaypointID IS NULL or something) 
) 
SELECT * FROM Waypoints 
+0

ORDER BYはどこですか? –

+0

@ JonasElfström:ORDER BYは必要ありません - アンカーである* 1つの行があり、その後は常にSomeRow.PrevWaypointID = previousRow.WaypointID'接続です。この順序は1つのウェイポイントとそれは前のものです。 –

+0

ああ、リンクリストの作成に失敗しました。 –

3

私はあなたの両方を試してみてgeographyタイプとして保存しようとしているお勧めします、その後

declare @point1 geography = 'POINT (-42 84)'; 
declare @point2 geography = 'POINT (-3 10)'; 
select @point1.STDistance (@point2) 

本当に最速何であるかを知っているでしょう。

+1

Typo? 2行目は 'declare @ point2 ...'でなければなりません。 – MusiGenesis

+0

はい、良い古いタイプミスです。 –

2

私の理解では、さらにSQLでカーソルを使用して、それが桁違いに高速フロントサイド・コードに反復するよりもまだあるということです。当時、ADOとDAOは問題の技術であったため、ADO.NETとDataSetsの登場により状況は少し変わってきました。

しかし、私はこのタイプのもののために特別に設計されたT-SQLが依然として効率的であると賭けています。

反復処理中に特別なロジックを適用する必要がある場合は例外ですが、正しく設定されたSQLカーソルが裏側で計算を実行すると、データセットのパフォーマンスが向上します。

可能な場合は、カーソルをSQLに置かないでください。 。 。

+0

他の人がより良い回答をしている間に投稿していました。 。 。 – XIVSolutions

2

Sql Server 2008(またはそれ以降)を使用している場合は、地理タイプを使用してサーバー上のすべての操作を行うことができます。 2点間の距離を計算するためのサンプルは次のとおりです。

SELECT geography::Point(lat1, lon1, 4326).STDistance(geography::Point(lat2, lon2, 4326)) 

これはカーソルなしでも使用できるかわかりませんが、

古いバージョンのSQL Serverを使用している場合でも、距離式を自分自身をストアドプロシージャとして書き込むことができますし、サーバー側もすべて実行できます。

セット全体をクライアントにダウンロードし、すべての計算をクライアント側で行うには、ダウンロード時間が計算時間よりもはるかに長いため、かなり長い時間がかかります。