Güncelleme , SQL Server 2012 çalıştırıyorsanız bkz: https://stackoverflow.com/a/10309947
Sorun, Over yan tümcesinin SQL Server uygulaması biraz sınırlı olmasıdır .
Oracle (ve ANSI-SQL) aşağıdakileri yapmanızı sağlar:
SELECT somedate, somevalue,
SUM(somevalue) OVER(ORDER BY somedate
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AS RunningTotal
FROM Table
SQL Server, bu soruna temiz bir çözüm sağlar. Bağırsak, bunun imlecin en hızlı olduğu nadir durumlardan biri olduğunu söylüyor, ancak büyük sonuçlarda bazı kıyaslamalar yapmak zorunda kalacağım.
Güncelleme hilesi kullanışlı ama oldukça kırılgan hissediyorum. Tam bir tabloyu güncelliyorsanız, birincil anahtar sırasına göre ilerleyecek gibi görünüyor. Tarihinizi artan birincil anahtar olarak ayarlarsanız probably
güvende olursunuz . Ancak belgelenmemiş bir SQL Server uygulama ayrıntısına güveniyorsunuz (ayrıca sorgu iki proc tarafından gerçekleştiriliyorsa ne olacağını merak ediyorum, bkz: MAXDOP):
Tam çalışma örnek:
drop table #t
create table #t ( ord int primary key, total int, running_total int)
insert #t(ord,total) values (2,20)
-- notice the malicious re-ordering
insert #t(ord,total) values (1,10)
insert #t(ord,total) values (3,10)
insert #t(ord,total) values (4,1)
declare @total int
set @total = 0
update #t set running_total = @total, @total = @total + total
select * from #t
order by ord
ord total running_total
----------- ----------- -------------
1 10 10
2 20 30
3 10 40
4 1 41
Bu alçalma bir kriter istediniz.
Bunu yapmanın en güvenli yolu İmleç olurdu, çapraz birleşmenin ilişkili alt sorgusundan daha hızlı bir büyüklük sırasıdır.
Mutlak en hızlı yol GÜNCELLEME hile. Bununla ilgili tek endişem, her koşulda güncellemenin doğrusal bir şekilde ilerleyeceğinden emin olmadığım. Sorguda açıkça söylenen hiçbir şey yok.
Alt satırda, üretim kodu için imleç ile giderdim.
Test verisi:
create table #t ( ord int primary key, total int, running_total int)
set nocount on
declare @i int
set @i = 0
begin tran
while @i < 10000
begin
insert #t (ord, total) values (@i, rand() * 100)
set @i = @i +1
end
commit
Test 1:
SELECT ord,total,
(SELECT SUM(total)
FROM #t b
WHERE b.ord <= a.ord) AS b
FROM #t a
-- CPU 11731, Reads 154934, Duration 11135
Test 2:
SELECT a.ord, a.total, SUM(b.total) AS RunningTotal
FROM #t a CROSS JOIN #t b
WHERE (b.ord <= a.ord)
GROUP BY a.ord,a.total
ORDER BY a.ord
-- CPU 16053, Reads 154935, Duration 4647
Test 3:
DECLARE @TotalTable table(ord int primary key, total int, running_total int)
DECLARE forward_cursor CURSOR FAST_FORWARD
FOR
SELECT ord, total
FROM #t
ORDER BY ord
OPEN forward_cursor
DECLARE @running_total int,
@ord int,
@total int
SET @running_total = 0
FETCH NEXT FROM forward_cursor INTO @ord, @total
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @running_total = @running_total + @total
INSERT @TotalTable VALUES(@ord, @total, @running_total)
FETCH NEXT FROM forward_cursor INTO @ord, @total
END
CLOSE forward_cursor
DEALLOCATE forward_cursor
SELECT * FROM @TotalTable
-- CPU 359, Reads 30392, Duration 496
Test 4:
declare @total int
set @total = 0
update #t set running_total = @total, @total = @total + total
select * from #t
-- CPU 0, Reads 58, Duration 139