2010-04-16 27 views
2

任何人都可以幫我改進SQL 2000中游標邏輯的性能。它在SQl2005和SQL2008中運行良好,但需要至少20分鐘才能在SQL 2000中運行。順便說一句,我永遠不會選擇使用遊標,並且我沒有寫這個代碼,只是試圖讓它運行得更快。將客戶升級到2005/2008並不是最近的選擇。幫助用更好的代碼替換這個SQL遊標

------------------------------------------------------------------------------- 
------- Rollup totals in the chart of accounts hierarchy 
------------------------------------------------------------------------------- 
DECLARE @B_SubTotalAccountID int, @B_Debits money, @B_Credits money, @B_YTDDebits money, @B_YTDCredits money 

DECLARE Bal CURSOR FAST_FORWARD FOR 
SELECT SubTotalAccountID, Debits, Credits, YTDDebits, YTDCredits FROM xxx 
    WHERE AccountType = 0 AND SubTotalAccountID Is Not Null and (abs(credits)+abs(debits)+abs(ytdcredits)+abs(ytddebits)<>0) 
OPEN Bal 

FETCH NEXT FROM Bal INTO @B_SubTotalAccountID, @B_Debits, @B_Credits, @B_YTDDebits, @B_YTDCredits 

--For Each Active Account 
WHILE @@FETCH_STATUS = 0 
BEGIN 

--Loop Until end of subtotal chain is reached 
WHILE @B_SubTotalAccountID Is Not Null 
    BEGIN 

    UPDATE xxx2 
    SET Debits = Debits + @B_Debits, 
    Credits = Credits + @B_Credits, 
    YTDDebits = YTDDebits + @B_YTDDebits, 
    YTDCredits = YTDCredits + @B_YTDCredits 
    WHERE GLAccountID = @B_SubTotalAccountID 

    SET @B_SubTotalAccountID = (SELECT SubTotalAccountID FROM xxx2 WHERE GLAccountID = @B_SubTotalAccountID) 

    END 

FETCH NEXT FROM Bal INTO @B_SubTotalAccountID, @B_Debits, @B_Credits, @B_YTDDebits, @B_YTDCredits 

END 

CLOSE Bal 
DEALLOCATE Bal 

回答

3
Update xx2 
Set Credits = Credits + X1.CreditTotal 
    , Debits = Debits + X1.DebitTotal 
    , YtdDebits = YtdDebits + X1.YtdDebitTotal 
    , YtdCredits = YtdCredits + X1.YtdDebitTotal 
From xx2 As X2 
    Join (
      Select SubTotalAccountID, Sum(Debits) As DebitTotal, Sum(Credits) As CreditTotal 
       , Sum(YtdDebits) As YtdDebitTotal, Sum(YtdCredits) As YtdCreditTotal 
      From xxx 
      Where AccountType = 0 
       And SubTotalAccountID Is Not Null 
       And (
        Credits <> 0 
        Or Debits <> 0 
        Or YtdCredits <> 0 
        Or YtdDebits <> 0 
        ) 
      Group By SubTotalAccountID 
      ) As X1 
     On X1.SubTotalAccountID = X2.GLAccountID 

沒有模式立即更換,我不知道如果xxx表將返回多行對於給定SubTotalAccountId。我認爲它可以按照這個列對值進行分組,以便每個SubTotalAccountId獲得一行。

我也在WHERE子句中替換了您對ABS的使用,僅對零進行檢查。這應該快得多。

此UPDATE語句應該是您的遊標的完整替代品。

+0

我總是喜歡遊標的平面更新。遊標是邪惡的。 有時需要,但仍然邪惡... – AllenG 2010-04-16 15:24:15

1

一對夫婦的建議:

1 - 使用Profiler來告訴你哪一部分運行速度慢 - 你可以得到一個持續時間爲每個語句

2 - 運行初始SELECT語句(遊標聲明),並檢查查詢計劃。它運行速度快嗎?它是否正確使用索引?

3 - 與更新語句同樣的事情 - 檢查查詢計劃和索引使用

4 - 更新後的「設置」聲明看起來很奇怪 - 這似乎得到一個值@B_SubTotalAccountID然後將其由「獲取下一個」