データを保存する必要がない場合(行が変更、追加、または削除されるたびに現在の合計を更新する必要があるため、保存しないでください)、および風変わりな更新を信頼しない場合(動作が保証されておらず、修正プログラム、サービスパック、アップグレード、または基になるインデックスや統計の変更によって動作が変わる可能性があるため、このタイプのクエリを実行時に試すことができます。これは、MVPの仲間であるHugo Kornelisが「セットベースの反復」を作成した方法です(彼はの章の1つに同様の記事を投稿しました) SQLServerMVPディープダイブ )。通常、現在の合計には、セット全体のカーソル、セット全体の風変わりな更新、または行数が増えるにつれてますます高価になる単一の非線形自己結合が必要になるため、ここでの秘訣は、有限要素をループすることです。セット内の要素(この場合、各ユーザーの月に関する各行の「ランク」-そして、そのランクのすべてのユーザー/月の組み合わせに対して各ランクを1回だけ処理するため、200,000行をループする代わりに、最大24回ループします。
DECLARE @t TABLE
(
[user_id] INT,
[month] TINYINT,
total DECIMAL(10,1),
RunningTotal DECIMAL(10,1),
Rnk INT
);
INSERT @t SELECT [user_id], [month], total, total,
RANK() OVER (PARTITION BY [user_id] ORDER BY [month])
FROM dbo.my_table;
DECLARE @rnk INT = 1, @rc INT = 1;
WHILE @rc > 0
BEGIN
SET @rnk += 1;
UPDATE c SET RunningTotal = p.RunningTotal + c.total
FROM @t AS c INNER JOIN @t AS p
ON c.[user_id] = p.[user_id]
AND p.rnk = @rnk - 1
AND c.rnk = @rnk;
SET @rc = @@ROWCOUNT;
END
SELECT [user_id], [month], total, RunningTotal
FROM @t
ORDER BY [user_id], rnk;
結果:
user_id month total RunningTotal
------- ----- ----- ------------
1 1 2.0 2.0
1 2 1.0 3.0
1 3 3.5 6.5 -- I think your calculation is off
2 1 0.5 0.5
2 2 1.5 2.0
2 3 2.0 4.0
もちろん、できます このテーブル変数からベーステーブルを更新しますが、これらの格納された値は、次にテーブルがDMLステートメントにアクセスされるまでしか有効ではないため、なぜ面倒なのですか?
UPDATE mt
SET cumulative_total = t.RunningTotal
FROM dbo.my_table AS mt
INNER JOIN @t AS t
ON mt.[user_id] = t.[user_id]
AND mt.[month] = t.[month];
暗黙の順序付けに依存していないため、これは100%サポートされており、サポートされていない風変わりな更新と比較してパフォーマンスを比較する価値があります。勝てなくても近づいても、とにかくIMHOでの使用を検討してください。
SQL Server 2012ソリューションに関して、MattはRANGE
について言及しています。 ただし、この方法ではディスク上のスプールを使用するため、ROWS
でもテストする必要があります。 RANGE
で実行するだけでなく 。ケースの簡単な例を次に示します。
SELECT
[user_id],
[month],
total,
RunningTotal = SUM(total) OVER
(
PARTITION BY [user_id]
ORDER BY [month] ROWS UNBOUNDED PRECEDING
)
FROM dbo.my_table
ORDER BY [user_id], [month];
これをRANGE UNBOUNDED PRECEDING
と比較してください またはROWS\RANGE
なし まったく(RANGE
も使用します オンディスクスプール)。上記の場合、全体的な期間と方法は低くなります 計画は少し複雑に見えますが、I / Oは少なくなります(追加のシーケンスプロジェクトオペレーター)。
最近、特定の累計シナリオで観察されたパフォーマンスの違いを概説したブログ投稿を公開しました。
http://www.sqlperformance.com/2012/07 / t-sql-queries / running-totals