[英]Optimize query within sql
我有以下算法
For R = FirstRowDBABACUS To LastRowDBABACUS ' R = Remboursement
LastInterestDate = ""
Do While Sheets("CI").Cells(R, 10).Value <> 0
For Inte = FirstRowDBABACUS To LastRowDBABACUS
'On commence par l'intérêt
If Sheets("CI").Cells(Inte, 3).Value <= DateArrete Then
LastInterestDate = "R" & Inte & "C" & 3
If Sheets("CI").Cells(Inte, 8).Value <> 0 Then
If Sheets("CI").Cells(R, 10).Value > Sheets("CI").Cells(Inte, 8).Value Then
'Modification du montant de Remboursement residuel
Sheets("CI").Cells(R, 10).Value = Sheets("CI").Cells(R, 10).Value - Sheets("CI").Cells(Inte, 8)
Sheets(RapproSheetName).Cells(Inte, 12).Value = Sheets(RapproSheetName).Cells(Inte, 8).Value
Sheets("CI").Cells(Inte, 8).Value = 0
Else
'Le montant ne suffit pas pour les intérêts
Sheets(RapproSheetName).Cells(Inte, 12).Value = Sheets(RapproSheetName).Cells(Inte, 12).Value + Sheets("CI").Cells(R, 10).Value
Sheets("CI").Cells(Inte, 8).Value = Sheets("CI").Cells(Inte, 8).Value - Sheets("CI").Cells(R, 10).Value
Sheets("CI").Cells(R, 10).Value = 0
Exit For
End If
End If
'Principal s'il reste quelque chose
If Sheets("CI").Cells(R, 10).Value <> 0 Then
If Sheets("CI").Cells(Inte, 9) <> 0 Then
If Sheets("CI").Cells(R, 10).Value > Sheets("CI").Cells(Inte, 9).Value Then
'Modification du montant de Remboursement residuel
Sheets("CI").Cells(R, 10).Value = Sheets("CI").Cells(R, 10).Value - Sheets("CI").Cells(Inte, 9)
Sheets(RapproSheetName).Cells(Inte, 11).Value = Sheets(RapproSheetName).Cells(Inte, 9).Value
Sheets("CI").Cells(Inte, 9).Value = 0
Else
'Le montant ne suffit pas pour le remboursmeent du principal
Sheets(RapproSheetName).Cells(Inte, 11).Value = Sheets(RapproSheetName).Cells(Inte, 11).Value + Sheets("CI").Cells(R, 10).Value
Sheets("CI").Cells(Inte, 9).Value = Sheets("CI").Cells(Inte, 9).Value - Sheets("CI").Cells(R, 10).Value
Sheets("CI").Cells(R, 10).Value = 0
Exit For
End If
End If
End If
Else
End If
Next Inte
我正在嘗試編寫代碼sql,它花費的時間太長且結果錯誤。
> declare @RefAbacus as nvarchar(100)
> set @RefAbacus ='002-00000001'
> SELECT
> RowNum = ROW_NUMBER() OVER (
> ORDER BY [RefAbacus]),
> * INTO #CI
> FROM [CI]
> WHERE [RefAbacus] = @RefAbacus
> order by date, TypeOperation
> SELECT
> RowNum = ROW_NUMBER() OVER (
> ORDER BY [RefAbacus]),
> * INTO #DBRapproEchRemb
> FROM [DBTmpRapproEchRemb]
> WHERE [RefAbacus] =@RefAbacus
> order by date, TypeOperation
>
> CREATE UNIQUE CLUSTERED INDEX IX_1 on #CI ([RefAbacus], RowNum)
> CREATE UNIQUE CLUSTERED INDEX IX_2 on #DBRapproEchRemb ([RefAbacus], RowNum)
> --declaration des variables
> DECLARE @MaxRownum int
> SET @MaxRownum = (SELECT
> MAX(RowNum)
> FROM #CI) -----------------------
> DECLARE @MinRownum int
> SET @MinRownum = (SELECT
> MIN(RowNum)
> FROM #CI)
>
> DECLARE @FR int;
> DECLARE @LR int;
> DECLARE @inte int;
> DECLARE @R int;
> DECLARE @remboursement AS float
> DECLARE @LastInterestDate AS nvarchar(50);
> DECLARE @i int;
> DECLARE @TolerancePart int;
>
> SET @FR = @MinRownum
> SET @LR = @MaxRownum
> SET @TolerancePart = 5;
> ----------------------------------------------------
>
> SET @R = (SELECT
> MIN(RowNum)
> FROM #CI)
> SET @inte = (SELECT
> MIN(RowNum)
> FROM #CI)
>
>
> WHILE @R <= @MaxRownum
> BEGIN
>
> while (SELECT [Remboursement] FROM #CI WHERE RowNum = @R ) <>0 and (SELECT [Remboursement] FROM #CI WHERE RowNum = @R ) IS NOT
> NULL
> begin
> SET @LastInterestDate = ''
> SET @inte = (SELECT
> MIN(RowNum)
> FROM #CI)-1
> WHILE @inte <= @MaxRownum
> BEGIN -- run your operation here
> --print @inte
> -- Condition 1
> SET @inte = @inte + 1;
> IF (SELECT Date FROM #CI WHERE RowNum = @inte)<= CONVERT(date, GETDATE())
>
> BEGIN
> SET @LastInterestDate = 'R' + CONVERT(nvarchar(50), @inte) + 'C3'
>
> -- Condition 2
> IF ((SELECT EchInteret FROM #CI
> WHERE RowNum = @inte) <> 0)
> BEGIN
>
> -- Condition 3
> IF ((SELECT [Remboursement] FROM #CI
> WHERE RowNum = @R) > (SELECT EchInteret FROM #CI
> WHERE RowNum = @inte))
> BEGIN ---------------------------------------
> -- Update 1
> print 'Update 1'
> UPDATE #CI
> SET [Remboursement] = R.[Remboursement] - isnull(INTE.EchInteret,0)
> FROM (SELECT * FROM #CI
> WHERE RowNum = @inte) INTE INNER JOIN (SELECT * FROM #CI
> WHERE RowNum = @R) R
> ON R.RefAbacus = INTE.RefAbacus WHERE #CI.RowNum = @R;
>
> -- Update 2
> UPDATE #CI
> SET EchInteret = 0
> FROM (SELECT * FROM #CI
> WHERE RowNum = @inte) INTE INNER JOIN (SELECT * FROM #CI
> WHERE RowNum = @R) R ON R.RefAbacus = INTE.RefAbacus
> WHERE #CI.RowNum = @inte;
>
> UPDATE #DBRapproEchRemb
> SET [PartEnInterêt] = isnull(EchInteret,0)
> WHERE RowNum = @inte;
>
>
> --SET @inte = @inte + 1;
> END
> ELSE -------------------------
> -- Update 3
> BEGIN
>
> UPDATE #DBRapproEchRemb
> SET [PartEnInterêt] = isnull(INTE.[PartEnInterêt],0) + R.Remboursement
> FROM (SELECT * FROM #CI
> WHERE RowNum = @R) R
> INNER JOIN (SELECT * FROM #DBRapproEchRemb
> WHERE RowNum = @inte) INTE ON R.RefAbacus = INTE.RefAbacus
> WHERE #DBRapproEchRemb.RowNum = @inte;
>
>
> UPDATE #CI
> SET EchInteret = isnull(INTE.EchInteret,0) - R.Remboursement
> FROM (SELECT * FROM #CI
> WHERE RowNum = @R) R INNER JOIN (SELECT * FROM #CI
> WHERE RowNum = @inte) INTE ON R.RefAbacus = INTE.RefAbacus
> WHERE #CI.RowNum = @inte;
>
> print 'ok'
> UPDATE #CI
> SET Remboursement = 0
> WHERE #CI.RowNum = @R;
>
> --------------------------------------------
> BREAK
> END
> END
>
> -- Condition 4
> IF ((SELECT [Remboursement]FROM #CI
> WHERE RowNum = @R) <> 0)
>
> BEGIN
> -- Condition 5
> IF ((SELECT EchPrincial FROM #CI
> WHERE RowNum = @inte) <> 0)
>
> BEGIN
>
> -- Condition 6
> IF ((SELECT [Remboursement] FROM #CI
> WHERE RowNum = @R) > (SELECT EchPrincial FROM #CI
> WHERE RowNum = @inte))
>
> -- Update 4
>
> BEGIN
> ----------------------------
>
> UPDATE #CI
> SET [Remboursement] = R.[Remboursement] - isnull(INTE.EchPrincial,0)
> FROM (SELECT*FROM #CI
> WHERE RowNum = @inte) INTE INNER JOIN (SELECT * FROM #CI
> WHERE RowNum = @R) R ON R.RefAbacus = INTE.RefAbacus
> WHERE #CI.RowNum = @R;
>
> UPDATE #DBRapproEchRemb
> SET PartEnPrincipal =isnull( EchPrincial,0)
> WHERE RowNum = @inte;
>
>
> UPDATE #CI
> SET EchPrincial = 0
> WHERE #CI.RowNum = @inte;
> print' avant break'
>
> END
> -----------
> ELSE
> -- Update 5
> BEGIN
>
>
> UPDATE INTE
> SET PartEnPrincipal = isnull(inte.PartEnPrincipal,0) + R.Remboursement
> FROM (SELECT * from #DBRapproEchRemb
> WHERE RowNum = @inte)INTE INNER JOIN (SELECT * FROM #CI
> WHERE RowNum = @R) R ON R.RefAbacus = INTE.RefAbacus
> WHERE INTE.RowNum = @inte;
>
>
> UPDATE INTE
> SET EchPrincial = inte.EchPrincial + R.Remboursement
> FROM #CI
> INTE INNER JOIN (SELECT * FROM #CI
> WHERE RowNum = @R) R ON R.RefAbacus = INTE.RefAbacus
> WHERE INTE.RowNum = @inte;
>
>
> UPDATE #CI
> SET Remboursement = 0
> WHERE #CI.RowNum = @R;
> print 'apres break'
>
> BREAK
> END
> END
>
> END
>
> END
>
> end
>
> END
> SET @R = @R + 1;
> END
。 。 。
您要做的第一件事就是獲取SQL以獲得正確的結果。 優化沒有產生正確結果的東西是沒有意義的。 這里的不幸消息是,在您完成特定的優化之前,我們無法真正為您提供幫助,因為我們需要知道正確的查詢是什么樣子。
完成此操作后,下一步就是調查執行計划,並查看查詢的內容。 您將要弄清楚查詢的哪一部分是最昂貴的部分,然后首先開始對該部分進行優化。 好的工具不僅會向您顯示計划的每個部分,而且還會顯示這些部分相對於計划的其余部分所花費的時間。 如果查詢或查詢批處理中有多個不同的語句,則還應顯示哪些語句最昂貴。 如果您使用的是SQL Server,則SQL Server Management Studio工具附帶了可接受的查詢計划查看器,該查看器提供了此類信息,如果丟失索引,甚至可以幫助建議索引。 例如,如果您要進行表掃描(獲取全部或很大一部分),則表將數百萬行僅用於查找一些值,這將導致性能不理想。 或者,如果您要對非常大的數據集進行排序,那么也會導致性能下降。 您的查詢也顯式循環。 如果它在大量行上循環,那將是昂貴的。 如果您可以嘗試擺脫顯式循環而轉而使用基於集合的操作,則查詢優化器可能能夠簡化某些步驟並極大地加快操作速度。 但這只是猜測,因為目前我沒有足夠的信息來幫助您。
但是,除此之外,除非我們知道有效的查詢(產生正確結果的查詢),您正在使用的特定SQL數據庫,架構的外觀以及各種表的大小,否則它將不會我們很容易為您提供具體建議。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.