распределите баланс по всем строкам таблицы в цикле plsql, чтобы получить оставшийся ноль - PullRequest
0 голосов
/ 30 марта 2019

Ниже приведены простые и типовые данные, я хочу распределить баланс по всем строкам таблицы.

* ** 1003 тысяча два * Пример

Balance = 2997 Balance = -2997 Balance = 997 Balance = -997

Строки таблицы

  1021  1021-955 = 66
  1021  1021-1021 = 0
  1021  1021-1021 = 0

Значения сверху 955+1021+1021 = 2997

Я хочу использовать для цикла или любым другим простым способом распределить баланс по всем строкам. Пожалуйста, смотрите код ниже, как я пытаюсь сделать

DECLARE
   l_balance       NUMBER := 2997;
   l_running_bal   NUMBER := 0;
   l_bal_flg       VARCHAR2 (1) := 'Y';


   CURSOR c
   IS
          SELECT 1021 installment
            FROM DUAL
      CONNECT BY LEVEL <= 3;
BEGIN
   FOR i IN c LOOP
      IF l_bal_flg = 'Y' THEN
         l_running_bal := l_balance - i.installment;
         l_bal_flg := 'N';
      ELSE
         l_running_bal := l_running_bal - i.installment;
      END IF;


      DBMS_OUTPUT.PUT_LINE (l_running_bal);
   END LOOP;
END;

Обновление

  1021  66
  1021  0
  1021  0

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

следующий фрагмент кода должен работать согласно логике, требуемой вами ..

DECLARE
   l_bal_flg              VARCHAR2 (10) := 'Y';
   l_install_amt          NUMBER := 1362;
   l_calcaulatedbalance   NUMBER := 59024;
   l_curr_bal             NUMBER := 0;
   l_tot_inst_amount             NUMBER := 0;
   l_last_bal_amount             NUMBER := 0;
   l_install_amount2             NUMBER := 0;

   l_last_bal_amount2             NUMBER := 0;
   l_residual_amt         NUMBER := 14125;
   l_installment_cnt      NUMBER := 34;
   l_install_seq          NUMBER := 1;
   l_bal_trans            NUMBER :=0;
   l_bal_trans_cnt            NUMBER :=0;
BEGIN
-- amount to be balanced at last before transaction
l_tot_inst_amount := l_calcaulatedbalance-l_residual_amt;
l_last_bal_amount := round(((l_tot_inst_amount/(l_installment_cnt-1)) -  l_install_amt) * (l_installment_cnt-1));

-- to get the transaction from which it has to be balanced
IF l_last_bal_amount <> 0
THEN
   l_last_bal_amount2 :=   ABS(l_last_bal_amount);
   l_install_amount2  :=   l_install_amt;
   l_BAL_TRANS := ceil(l_last_bal_amount2/l_install_amt);
   -- to get the amount to be added on first transaction to be balanced
loop
exit when l_last_bal_amount2 < l_install_amt;
l_last_bal_amount2 := l_last_bal_amount2 - l_install_amt;
end loop;

-- to get the exact transaction count on which first balance to be made
l_bal_trans_cnt :=l_installment_cnt-l_bal_trans;
END IF;

   FOR j IN 1 .. l_installment_cnt LOOP

-- adjustment at the transactions to be balanced
         IF l_bal_trans_cnt = l_install_seq THEN
            l_install_amt := l_install_amount2+(l_last_bal_amount2*(l_last_bal_amount/ABS(l_last_bal_amount)));

        elsif l_install_seq > l_bal_trans_cnt  and l_last_bal_amount >0  then
        l_install_amt := l_install_amount2+l_install_amount2;
         END IF;  



      IF l_residual_amt <> 0 THEN
         IF l_installment_cnt = l_install_seq THEN
            l_install_amt := l_residual_amt;
         END IF;
         -- if balance to be paid is the residual amount then no installment to be paid for the current month 
         IF l_curr_bal = l_residual_amt and l_installment_cnt <> l_install_seq THEN
            l_install_amt := 0;
         END IF;         
      END IF;


      IF l_bal_flg = 'Y' THEN
         l_curr_bal := l_calcaulatedbalance - l_install_amt;
         l_bal_flg := 'N';
      ELSE
         l_curr_bal := l_curr_bal - l_install_amt;
      END IF;

      l_install_seq := l_install_seq + 1;

      DBMS_OUTPUT.PUT_LINE (l_install_seq||' '||l_install_amt || '  ' || l_curr_bal);


   END LOOP;
END;


-- output:
for calculated balance 59024
34 1315  14125
35 14125  0

for calculated balance 63024
31 1362  22164
32 2591  19573
33 2724  16849
34 2724  14125
35 14125  0

for calculated balance 55024
31 1362  14164
32 39  14125
33 0  14125
34 0  14125
35 14125  0
1 голос
/ 30 марта 2019

Думаю, это будет сделано

set serverout on size 20000
DECLARE
   l_balance       NUMBER := 2997;
   l_sub           NUMBER;

   CURSOR c
   IS
          SELECT 1021 installment
            FROM DUAL
      CONNECT BY LEVEL <= 3;
BEGIN
   FOR i IN c LOOP
      l_sub := greatest(least(l_balance, i.installment),-i.installment);
      l_balance := l_balance - l_sub;
      DBMS_OUTPUT.PUT_LINE (i.installment||' '||(i.installment-l_sub));
   END LOOP;
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...