我编写了一个相当大的存储过程,以使用几个不同的数据集运行一些计算。当前,它使用光标在结果之间循环并运行一些计算。然后,它存储这些“先前行”计算,然后在下一次迭代中使用这些计算。我已阅读,以尽可能避免出现游标以提高性能。我希望它能尽可能地扩展,并且只需要任何建议。我一直在想也许LAG功能可以在这里提供帮助,但没有任何运气。我正在使用Azure中托管的MS SQL。这是当前过程:
CREATE Procedure [dbo].[spCreateAmoritzation]
@AccountNumber varchar(50)
AS
SET NOCOUNT ON;
BEGIN TRY
DECLARE @principalRemaining DECIMAL(10,2);
DECLARE @AmtFinanced decimal(10,2);
DECLARE @APR decimal(27,25);
DECLARE @ContractDate datetime;
DECLARE @PrincipalBalance decimal;
SET @PrincipalBalance = 5000;
SELECT Top 1 @AccountNumber = AccountNumber,
@AmtFinanced = AmtFinanced,
@APR = APR,
@ContractDate = ContractDate
FROM Account s
WHERE AccountNumber = @AccountNumber
DECLARE @interestRemaining DECIMAL(10,2);
DECLARE @principalCollected DECIMAL(10,2);
DECLARE @interestPerDiem DECIMAL(10,9);
SET @interestRemaining = 0;
SET @principalCollected = 0;
SET @principalRemaining = @AmtFinanced;
DECLARE @RowCount INT;
IF @APR > 1
SET @APR = @APR/100.00;
DECLARE th_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT EffectiveDate, Principal,Type
FROM Transactions
WHERE AccountID = @AccountNumber
ORDER BY Id ASC
OPEN th_cursor
DECLARE @EffectiveDate datetime;
DECLARE @Principal DECIMAL(18,2);
DECLARE @Type varchaR(50);
DECLARE @interestEarned decimal(10,2);
FETCH NEXT FROM th_cursor
INTO @EffectiveDate, @Principal ,@Type
IF @@FETCH_STATUS <> 0
BEGIN
CLOSE th_cursor;
DEALLOCATE th_cursor;
RETURN
END
DECLARE @Table TABLE (
AccountNumber varchar(50),
PaymentDate datetime,
Payment decimal(18,2),
Type varchar(30),
InterestPerDiem decimal(10,9) null,
InterestEarned decimal(10,2) null,
InterestRemaining decimal(10,2) null,
PrincipalCollected decimal(18,2) null,
PrincipalRemaining decimal(18,2)
)
INSERT INTO @Table
(AccountNumber,Payment, PaymentDate, Type, PrincipalRemaining )
VALUES
(@AccountNumber, 0, @ContractDate, 'PAYMENT', @principalRemaining)
WHILE @@FETCH_STATUS = 0
BEGIN
SET @interestPerDiem = (@APR/365) * @principalRemaining
SET @interestEarned = ((DATEDIFF(DAY,@ContractDate, @EffectiveDate) * @interestPerDiem) + @interestRemaining)
IF (@Type = 'PAYMENT')
BEGIN
IF (@interestEarned - @Principal > 0)
SET @interestRemaining = @interestEarned - @Principal;
ELSE
SET @interestRemaining = 0
IF(@interestEarned - @Principal > 0)
SET @principalCollected = 0
ELSE
SET @principalCollected= @Principal - @interestEarned
SET @principalRemaining = @principalRemaining - @principalCollected
END
IF (@Type = 'PRNCRADJ')
BEGIN
SET @principalRemaining = @principalRemaining - @Principal
SET @interestPerDiem = NULL
set @interestEarned = NULL
set @principalCollected = NULL
END
IF (@Type = 'PRNDRADJ')
BEGIN
SET @principalRemaining = @principalRemaining+ @Principal
SET @interestPerDiem = NULL
set @interestEarned = NULL
set @principalCollected = NULL
END
INSERT INTO @Table
(AccountNumber, PaymentDate, Payment, Type, InterestPerDiem, InterestRemaining, InterestEarned, PrincipalCollected, PrincipalRemaining )
VALUES
(@AccountNumber, @EffectiveDate, @Principal, @Type, @interestPerDiem, @interestRemaining, @interestEarned, @principalCollected, @principalRemaining)
SET @ContractDate = @EffectiveDate
FETCH NEXT FROM th_cursor INTO @EffectiveDate, @Principal ,@Type
END
CLOSE th_cursor;
DEALLOCATE th_cursor;
INSERT INTO Results
(AccountNumber, PaymentDate, Payment, Type, InterestPerDiem, InterestRemaining, InterestEarned, PrincipalCollected, PrincipalRemaining )
SELECT * from @Table;
UPDATE Calculator
SET Variance = @principalRemaining, LastCalculated = GetDate()
WHERE AccountID = @AccountNumber;
END TRY
BEGIN CATCH
return
END CATCH
GO
以下是“交易”表中的示例数据:
AccountID EffectiveDate Principal Type
12345 10/3/2013 450.00 PAYMENT
12345 10/30/2013 419.34 PAYMENT
12345 12/2/2013 419.34 PAYMENT
12345 1/17/2014 414.00 PAYMENT
12345 2/12/2014 420.00 PAYMENT
以下是“结果”表中的示例输出:
AccountID Payment Type InterestPerDiem InterestRemaining InterestEarned PrincipalCollected PrincipalRemaining
12345 0.00 PAYMENT NULL NULL NULL NULL 10875.82
12345 244.19 PAYMENT 2.976697036 119.07 0.00 125.12 10750.70
12345 244.19 PAYMENT 2.942451863 85.33 0.00 158.86 10591.84
12345 244.19 PAYMENT 2.898972099 86.97 0.00 157.22 10434.62
12345 244.19 PAYMENT 2.855941200 114.24 0.00 129.95 10304.67
该函数的输出是它将获取一个帐户并获得一些基本信息,例如APR,融资金额和合同日期。
然后,它将循环遍历该帐户的交易清单,其中包括日期和付款。当它遍历交易的每一行时,它将使用APR和其他一些指标来计算利息。最终,该计算结果集将被写入表中。