Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tính tổng số đang chạy trong SQL Server

Cập nhật , nếu bạn đang chạy SQL Server 2012, hãy xem:https://stackoverflow.com/a/10309947

Vấn đề là việc triển khai mệnh đề Over của SQL Server có phần hạn chế.

Oracle (và ANSI-SQL) cho phép bạn làm những việc như:

 SELECT somedate, somevalue,
  SUM(somevalue) OVER(ORDER BY somedate 
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
          AS RunningTotal
  FROM Table

SQL Server không cung cấp cho bạn giải pháp rõ ràng cho vấn đề này. Ruột của tôi đang nói với tôi rằng đây là một trong những trường hợp hiếm hoi mà con trỏ là nhanh nhất, mặc dù tôi sẽ phải thực hiện một số phép đo điểm chuẩn cho các kết quả lớn.

Thủ thuật cập nhật rất tiện dụng nhưng tôi cảm thấy nó khá mỏng manh. Có vẻ như nếu bạn đang cập nhật một bảng đầy đủ thì nó sẽ tiến hành theo thứ tự của khóa chính. Vì vậy, nếu bạn đặt ngày của mình làm khóa chính tăng dần, bạn sẽ probably được an toàn. Nhưng bạn đang dựa vào chi tiết triển khai SQL Server không có tài liệu (cũng như nếu truy vấn kết thúc được thực hiện bởi hai procs, tôi tự hỏi điều gì sẽ xảy ra, hãy xem:MAXDOP):

Mẫu làm việc đầy đủ:

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

Bạn đã yêu cầu một điểm chuẩn, đây là mức thấp nhất.

Cách AN TOÀN nhanh nhất để thực hiện việc này là Con trỏ, nó là một thứ tự có cường độ nhanh hơn so với truy vấn phụ tương quan của phép nối chéo.

Cách nhanh nhất tuyệt đối là thủ thuật CẬP NHẬT. Mối quan tâm duy nhất của tôi với nó là tôi không chắc chắn rằng trong mọi trường hợp, cập nhật sẽ tiến hành theo cách tuyến tính. Không có gì trong truy vấn nói rõ ràng như vậy.

Tóm lại, đối với mã sản xuất, tôi sẽ sử dụng con trỏ.

Dữ liệu thử nghiệm:

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

Thử nghiệm 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 

Thử nghiệm 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

Thử nghiệm 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

Thử nghiệm 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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server tương đương với kiểu dữ liệu MySQL enum?

  2. ORDER BY (CHỌN NULL) nghĩa là gì?

  3. Cách tăng kích thước tệp của tệp dữ liệu trong SQL Server (T-SQL)

  4. COS () Ví dụ trong SQL Server

  5. Làm cách nào để hiển thị cấu trúc bảng trong truy vấn SQL Server?