Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
jung1975
Aged Yak Warrior
503 Posts |
Posted - 2003-05-21 : 22:33:29
|
| I would like to see the different approaches to solve this problem that sleezy have posted on Database Journal. /*I HAVE WRITTEN A prcRepaymentFacility PROCEDURE TO ALLOCATE INTEREST PAID when payment is recieved. THE PROBLEM IS I'M USING THREE CURSORS TO PROCESS MY DATA AS THIS REQUIRES ROW BY ROW MANIPULATION. WHAT OTHER TECHNIQUE CAN I USE TO PROCESS THIS DATA AND IMPROVE PERFORMANCE OF MY PROCEDURE THIS QUERY RUNS FOR A VERY LONG TIME. SO IN 1:40HRS I WOULD HAVE 4402 RECORDS. I HAVE 6 MILLION RECORDS TO GO THROUGH. HOW CAN I OPTIMIZE THIS QUERY.I'VE TRIED ALL I CAN SHOULD IT BE RE-WRITTEN AS TWO SEPARATE FUNCTIONS ??? I'M STUCK PLEASE ASSIST I NEED TO HAVE IT READY BY TUES BUT I CAN'T OPTIMISE IT.. --SCROLL THROUGH RECORDS WITHOUT A CURSOR ..... -- DECLARE @OBJECT_KEY VARCHAR(50) -- SET @OBJECT_KEY = '' -- -- WHILE @OBJECT_KEY IS NOT NULL -- BEGIN -- SELECT TOP 20 @OBJECT_KEY = MIN(OBJECT_KEY) -- FROM REPAYMENT_TABLE -- WHERE OBJECT_KEY > @OBJECT_KEY -- -- IF @OBJECT_KEY IS NOT NULL -- SELECT @OBJECT_KEY + ............ETC -- -- END */IF OBJECT_ID('prcRepaymentFacility') IS NOT NULLDROP PROC prcRepaymentFacilityGOSET QUOTED_IDENTIFIER ON GOSET ANSI_NULLS ON GOCREATE PROCEDURE prcRepaymentFacilityAS BEGIN TRANUPDATE aSET a.paid_interest = 0 ,a.paid_principal = 0FROM REPAYMENT_TABLE aDECLARE @X intDECLARE @i intDECLARE @j intDECLARE @k intDECLARE @m intDECLARE @n intDeclare @Acc_No varchar (50)DECLARE @Repay_No intDECLARE @Due_Date datetimeDECLARE @Due_Principal moneyDECLARE @Due_Interest moneyDeclare @Due_Penalty_on_Interest moneyDECLARE @Paid_Principal moneyDECLARE @Paid_Interest moneyDeclare @Paid_Penalty_on_Interest moneyDeclare @Interest_Payer moneyDeclare @Principal_Payer moneyDECLARE @Repay_Amt moneyDECLARE @RPay_Date varchar (30)SET @X = 0DECLARE RS_ALL CURSOR FOR --LOCAL FAST_FORWARD FORSELECT DISTINCT Object_Key FROM REPAYMENT_TABLEOPEN RS_AllFETCH NEXT FROM RS_All INTO @Acc_No WHILE @@FETCH_STATUS = 0 BEGINSET @X = @X + 1SELECT @XDECLARE @Tmp TABLE ( AccountNo VARCHAR(15) ,TotalAmount MONEY ,PaidDate DATETIME )INSERT INTO @TmpSELECT AccountNo ,TotalAmount ,CONVERT(DATETIME,PaidDate)FROM ZA15100P_TotalsWHERE AccountNo = @Acc_No--<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<---------SET @I = 0DECLARE RS CURSOR FOR --LOCAL FAST_FORWARD FORSELECT Repayment_Number ,Due_Date ,Due_Principal ,Due_Interest ,Paid_Principal ,Paid_Interest ,Due_Penalty_On_Interest ,Paid_Penalty_On_InterestFROM REPAYMENT_TABLEWHERE Object_Key = @Acc_no ORDER BY Repayment_Number ASCOPEN RSFETCH NEXT FROM RS INTO @Repay_No ,@Due_Date ,@Due_Principal ,@Due_Interest ,@Paid_Principal ,@Paid_Interest ,@Due_Penalty_on_Interest ,@Paid_Penalty_on_InterestWHILE @@FETCH_STATUS = 0 BEGINSET @I = @I + 1 IF (SELECT COUNT(*) FROM @Tmp WHERE CONVERT(VARCHAR(50),DATEPART(YEAR ,CONVERT(DATETIME,Paiddate))) + CONVERT(VARCHAR(50),DATEPART(MONTH ,CONVERT(DATETIME,Paiddate))) = CONVERT(VARCHAR(50),DATEPART(YEAR ,CONVERT(DATETIME,@due_date))) + CONVERT(VARCHAR(50),DATEPART(MONTH ,CONVERT(DATETIME,@due_date)))) > 0BEGIN DECLARE RS_1 CURSOR FORSELECT TotalAmount * -1 ,Paiddate FROM @Tmp WHERE CONVERT(VARCHAR(50),DATEPART(YEAR ,CONVERT(DATETIME,Paiddate))) + CONVERT(VARCHAR(50),DATEPART(MONTH ,CONVERT(DATETIME,Paiddate))) = CONVERT(VARCHAR(50),DATEPART(YEAR ,CONVERT(DATETIME,@due_date))) + CONVERT(VARCHAR(50),DATEPART(MONTH ,CONVERT(DATETIME,@due_date)))OPEN RS_1FETCH NEXT FROM RS_1 INTO @Repay_Amt ,@RPay_DateCLOSE RS_1DEALLOCATE RS_1END --End For Count check of RS_1--Goto Skipper--------------------- ------------------------------------------------------Populate Paid Interest & Principal-----------------------------------------------------------------------------------Start_Int:SET @j = @i + 1SET @k = 0 WHILE @J > 1 AND @Repay_Amt > 0 BEGIN SET @k = @k + 1SET @j = @j - 1-------------------- -------------------------------------------------------Populate Paid Interest----------------------------------------------------------------------------------------------DECLARE RS_2 CURSOR FORSELECT Due_Interest ,Paid_InterestFROM REPAYMENT_TABLEWHERE Repayment_Number = @j AND Object_Key = @Acc_noOPEN RS_2FETCH NEXT FROM RS_2 INTO @Due_Interest ,@Paid_InterestIF @Due_Interest - @Paid_Interest > 0BEGINIF @Due_Interest - @Paid_Interest - @Repay_Amt < 0BEGINSET @Interest_Payer = @Due_Interest - @Paid_InterestEND ELSEBEGINSET @Interest_Payer = @Repay_Amt ENDEND ELSEBEGINSET @Interest_Payer = 0 END--SELECT @Interest_PayerUPDATE REPAYMENT_TABLESET Paid_interest = @Paid_Interest + @Interest_PayerWHERE CURRENT OF RS_2 CLOSE RS_2DEALLOCATE RS_2 SET @Repay_Amt = @Repay_Amt - @Interest_PayerSET @Interest_Payer = 0 -- goto Start_Int--------------------------------------------------------------------------------------------------------------Populate the Paid Principal Amounts-----------------------------------------------------------------------SET @m = @i + 1SET @n = 0 WHILE @m > 1 and @Repay_Amt > 0 --and @n < 2 BEGIN SET @n = @n + 1 SET @m = @m - 1 DECLARE RS_2 CURSOR FORSELECT Due_Principal ,Paid_Principal FROM REPAYMENT_TABLE WHERE repayment_number = @m AND object_Key = @Acc_no OPEN RS_2FETCH NEXT FROM RS_2 INTO @Due_Principal ,@Paid_PrincipalIF @Due_Principal - @Paid_Principal > 0 BEGINIF @Due_Principal - @Paid_Principal - @Repay_Amt < 0 BEGINSET @Principal_Payer = @Due_Principal - @Paid_Principal ENDELSE BEGINSET @Principal_Payer = CASE WHEN @Repay_Amt > 0 THEN @Repay_Amt ELSE 0 END END END ELSE BEGIN SET @Principal_Payer = 0 END --Select @Interest_PayerUPDATE REPAYMENT_TABLESET Paid_Principal = @Paid_Principal + @Principal_PayerWHERE CURRENT OF RS_2 CLOSE RS_2DEALLOCATE RS_2 SET @Repay_Amt = @Repay_Amt - @Principal_PayerSET @Principal_Payer = 0 END IF @Repay_Amt > 0 BEGIN DECLARE RS_3 CURSOR FORSELECT Paid_PrincipalFROM REPAYMENT_TABLE WHERE Repayment_Number = @i AND Object_Key = @Acc_no OPEN RS_3FETCH NEXT FROM RS_3 INTO @Paid_PrincipalUPDATE REPAYMENT_TABLESET Paid_Principal = @Paid_Principal + @Repay_AmtWHERE CURRENT OF RS_3 CLOSE RS_3 DEALLOCATE RS_3 END END--------------------------------------------------------------SET @Repay_Amt = 0 FETCH NEXT FROM RSINTO @Repay_No ,@Due_Date ,@Due_Principal ,@Due_Interest ,@Paid_Principal ,@Paid_Interest ,@Due_Penalty_on_Interest ,@Paid_Penalty_on_InterestSkipper:ENDCLOSE RSDEALLOCATE RS--*************************************************FETCH NEXT FROM RS_All INTO @Acc_NoENDCLOSE RS_AllDEALLOCATE RS_AllCOMMIT TRANGOSET QUOTED_IDENTIFIER OFF GOSET ANSI_NULLS ON GO |
|
|
rrb
SQLTeam Poet Laureate
1479 Posts |
Posted - 2003-05-22 : 20:09:44
|
| Hi jungYour problem is not optimization, it is the fact that you are using cursors which is so slow. I've started looking at your problem and from what I can see, it looks as if you don't need cursors at all. At the moment I don't have the time to reverse engineer the problem from your code (sorry). Could you post some DDL (table definitions) with some example data, and your problem specification (ie interest calculation formulae), and I'll try a solution. Cheers--I hope that when I die someone will say of me "That guy sure owed me a lot of money" |
 |
|
|
|
|
|
|
|