web-dev-qa-db-ja.com

このカーソルをより良く機能させる方法

テーブルがあり、ローン金額に支払いを適用しようとしています。支払いは、次のローンに進む前に、ゼロになるまで最初のローンに適用する必要があります。

まず、カーソルは私の強みではないと言わざるを得ませんが、試してみました。カーソルがpmnt_amtからDEAL_FP_CALC_BEG_BAL_AMTをゼロになり、残りの支払いを次のDEAL_FP_CALC_BEG_BAL_AMTに適用するまで、カーソルを取得できません。

たとえば、5000のDEAL_FP_CALC_BEG_BAL_AMTは次のように支払われます。

5000.00- 1235.3 = 3764.7
3764.7 - 1122.00 = 2642.7
2642.7 - 1035.3 = 1607.4
1607.4 - 1005.4 = 602.00
602.4 -1005.2 = (403.2) Loan paid off
(403.2) + 7500 - 1235.3(next payment) = 5861.5 until this is paid

テーブルは

FP_MERCH_ID  PMNT_SEQ_ID  PMNT_AMT  PMNT_DT   DEAL_FP_BAL_AMT  FUND_DT
2359         1122         1235.3    10/1/15   5000             9/1/15
2359         1123         1122      10/12/15  5000             9/1/15
2359         1124         1035.3    10/19/15  5000             9/1/15
2359         1125         1005.4    10/24/15  5000             9/1/15
2359         1126         1105.2    10/29/15  5000             9/1/15
2359         1127         1235.3    11/3/15   7500             10/31/15
2359         1128         1122      11/8/15   7500             10/31/15
2359         1129         1035.3    11/13/15  7500             10/31/15
2359         1130         1005.4    11/18/15  7500             10/31/15
2359         1131         1105.2    11/23/15  7500             10/31/15

これが私のコードです。 DEAL_FP_CALC_BEG_BAL_AMTはローン金額です。

--DECLARE @COUNTER INT
DECLARE @PAYMENT INT
DECLARE @BALANCE INT
--DECLARE @MAXCOUNT INT
DECLARE @RESULTS INT
DECLARE @FP_CALC_BEG_BAL_AMT INT
SET @FP_CALC_BEG_BAL_AMT = (SELECT MAX(DEAL_FP_CALC_BEG_BAL_AMT)
                        From LOOPDATA_NEW where FP_MERCH_ID = 2359
                      )

DECLARE VINTAGE CURSOR 
    FOR SELECT PMNT_AMT From LOOPDATA_NEW Where FP_MERCH_ID = 2359  
                        Group by FP_MERCH_ID, PMNT_SEQ_ID, PMNT_AMT


OPEN VINTAGE 

    FETCH NEXT FROM VINTAGE INTO @PAYMENT

    WHILE @@FETCH_STATUS = 0 

    BEGIN 

    SET @BALANCE = @FP_CALC_BEG_BAL_AMT - @PAYMENT  
        /* begin
        set @RESULTS = @BALANCE - @PAYMENT
        end */
    PRINT @BALANCE

FETCH NEXT FROM VINTAGE INTO @PAYMENT

END
CLOSE VINTAGE
DEALLOCATE VINTAGE
1
CJack

ここで実際にバランスを減らすことはありません。私はあなたがこれをするつもりだと思います:

SET @BALANCE = @FP_CALC_BEG_BAL_AMT;
OPEN VINTAGE;
FETCH NEXT FROM VINTAGE INTO @PAYMENT;
WHILE @@FETCH_STATUS = 0
BEGIN
  SET @BALANCE = @BALANCE - @PAYMENT;
FETCH NEXT FROM VINTAGE INTO @PAYMENT;
END
CLOSE VINTAGE;
DEALLOCATE VINTAGE;

この例では、開始残高を初期ローン金額に設定します。次に、カーソルを繰り返すたびに、支払い額だけ残高を減らします。

なぜカーソルを使用したのかわかりません。理由はあると思いますが、以下ではカーソルを使用しないと目的の結果が得られませんか?

DECLARE @TOTAL_PAYMENTS INT;
    SET @TOTAL_PAYMENTS = (SELECT SUM(PMNT_AMT) 
                             From LOOPDATA_NEW 
                            Where FP_MERCH_ID = 2359  
                         Group by FP_MERCH_ID, PMNT_SEQ_ID, PMNT_AMT);
    SET @BALANCE = @FP_CALC_BEG_BAL_AMT - @TOTAL_PAYMENTS;

また、コードで残高と支払いをINTにキャストすると、小数点以下の精度が失われ、実際の例である場合、お金を失う可能性があります。これらの値を正しくキャプチャできるように、DECIMALなどの正確なデータ型を使用することを忘れないでください。

コメントに基づいて編集

すべての場合に最大のローンを返すだけの理由は、コードの次の行のためです。

DECLARE @FP_CALC_BEG_BAL_AMT INT
    SET @FP_CALC_BEG_BAL_AMT = (SELECT MAX(DEAL_FP_CALC_BEG_BAL_AMT)
                                  From LOOPDATA_NEW 
                                 where FP_MERCH_ID = 2359);

ここで最大のローンを取得するだけです。各ローンをループしてから各支払いをループする場合は、次のようにします。

DECLARE @loan DECIMAL(9,2) = 0;
DECLARE @balance DECIMAL(9,2) = 0;
DECLARE @payment DECIMAL(9,2) = 0;

DECLARE loans CURSOR 
    FOR (SELECT DISTINCT DEAL_FP_CALC_BEG_BAL_AMT
           From LOOPDATA_NEW 
          where FP_MERCH_ID = 2359);
 OPEN loans;
FETCH NEXT FROM loans INTO @loan;
WHILE @@FETCH_STATUS = 0
BEGIN
  SET @balance = @balance + @loan;

  DECLARE payments CURSOR 
      FOR (SELECT PMNT_AMT 
            From LOOPDATA_NEW 
           Where FP_MERCH_ID = 2359
        Group by FP_MERCH_ID, PMNT_SEQ_ID, PMNT_AMT);

   OPEN payments;
  FETCH NEXT FROM payments INTO @payment;
  WHILE @@FETCH_STATUS = 0 AND @balance > 0
  BEGIN
    SET @balance = @balance - @payment;
  FETCH NEXT FROM payments INTO @payment;
  END
  CLOSE payments;
  DEALLOCATE payments;
FETCH NEXT FROM loans INTO @loan;
END
CLOSE loans;
DEALLOCATE loans;
PRINT @balance;

Aaron Bertrandは、 this 質問の現在の合計を計算するために使用できるさまざまな方法について素晴らしい答えを提供します。長期的には役立つと思いますので、ぜひチェックしてみてください。

1
Mr.Brownstone