Mysql
 sql >> база данни >  >> RDS >> Mysql

MySql заявка за текуща корекция на баланса

Не мисля, че това може да се направи с помощта на код, базиран на набор, тъй като трябва да прочетете напред и да прочетете обратно. Нещо процедурно може да работи. С помощта на курсор и временна таблица мога да постигна почти това (трябва да добавите неща, за да гарантирате, че кумулативният баланс няма да стане отрицателен). От това, което казвате, първата транзакция никога не може да вземе отрицателно салдо, но бих проверил за това. Обърнете внимание, че вземанията от кредитния пул може да дойдат от по-късна дата от дебита, за който вземането компенсира - тъй като салдото никога не може да стане отрицателно, това не би трябвало да е проблем (sic). И разбира се, не бих очаквал изпълнението да бъде страхотно.

DROP TABLE IF EXISTS T;
create table t
(trx_no int, trx_date date,    Opening int,debit int,  credit int);
insert into t values
(1    ,   '2019-10-01' , 200  ,   0     ,  100),    
(2    ,   '2019-10-02' , 200  ,   0     ,  100),    
(3    ,   '2019-10-03' , 200  ,   100   ,  0  ),     
(4    ,   '2019-10-03' , 200  ,   400   ,  0  ),    
(5    ,   '2019-10-03' , 200  ,   0     ,  200),      
(6    ,   '2019-10-04' , 200  ,   0     ,  100),      
(7    ,   '2019-10-05' , 200  ,   100   ,  0  ),
(8    ,   '2019-10-05' , 200  ,   0     ,  400);

DROP TABLE IF EXISTS stmT;
create table stmt
(trx_no int, trx_date date,    Opening int,debit int,  credit int, cumbal int);




drop procedure if exists p;
delimiter $$
create procedure p()
begin

 declare v_trx_no int;
 declare v_dt date;
 declare v_debit int;
 declare v_credit int;

 declare h_trx_no int;
 declare h_dt date;
 declare h_credit int;

 declare opbal int;
 declare rbal  int;
 declare done int default 0;
 declare cur cursor for select trx_no,trx_date,debit,credit from t order by trx_date,trx_no;
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

 select opening into opbal from t order by trx_no limit 1;
 set rbal = opbal;
 drop table if exists creditpool;
 create temporary table if not exists creditpool as select trx_no,trx_date,credit,0 as used from t where  credit > 0; 
 #select * from creditpool;
    open cur;
    cursorloop:loop
        fetch cur into v_trx_no,v_dt,v_debit,v_credit;
         if done = true then  
        leave cursorloop;
         end if;  
         if v_credit > 0 and exists (select 1 from creditpool where trx_no = v_trx_no and used = 0) then 
             if v_credit > 0 then
                 insert into stmt values (v_trx_no,v_dt,opbal,v_debit,v_credit, rbal + v_credit);
                 set rbal = rbal + v_credit;
                 update creditpool set used = 1 where trx_no = v_trx_no; 
            end if;
         end if;
         if v_debit > 0 and v_debit <= rbal then
             insert into stmt values (v_trx_no,v_dt,opbal,v_debit,v_credit, rbal - v_debit);
             set rbal = rbal - v_debit;
         elseif v_debit > 0 and v_debit > rbal then
             poolloop: loop
                        select trx_no,trx_date,credit
                            into h_trx_no,h_dt,h_credit
                            from creditpool
                            where used = 0 
                            order by trx_date,trx_no limit 1;
                        insert into stmt values (h_trx_no,h_dt,opbal,0,h_credit, rbal + h_credit);
                        set rbal = rbal + h_credit;
                        update creditpool set used = 1 where trx_no = h_trx_no; 

                        if v_debit <= rbal then
                            insert into stmt values (v_trx_no,v_dt,opbal,v_debit,v_credit, rbal - v_debit);
                            set rbal = rbal - v_debit;
                            leave poolloop;
                        end if;
             end loop poolloop;           
         end if;
    end loop cursorloop;
    close cur;
end $$
delimiter ;
truncate stmt;
call p();
select * from stmt;

+--------+------------+---------+-------+--------+--------+
| trx_no | trx_date   | Opening | debit | credit | cumbal |
+--------+------------+---------+-------+--------+--------+
|      1 | 2019-10-01 |     200 |     0 |    100 |    300 |
|      2 | 2019-10-02 |     200 |     0 |    100 |    400 |
|      3 | 2019-10-03 |     200 |   100 |      0 |    300 |
|      5 | 2019-10-03 |     200 |     0 |    200 |    500 |
|      4 | 2019-10-03 |     200 |   400 |      0 |    100 |
|      6 | 2019-10-04 |     200 |     0 |    100 |    200 |
|      7 | 2019-10-05 |     200 |   100 |      0 |    100 |
|      8 | 2019-10-05 |     200 |     0 |    400 |    500 |
+--------+------------+---------+-------+--------+--------+
8 rows in set (0.00 sec)

Обърнете внимание, че резултатът е малко по-различен от желания от вас резултат, тъй като вземането се извършва само когато е необходимо.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Проблем с инсталацията на Ruby on Rails (Windows)

  2. Заявката за актуализиране на Mysql с подготвено изявление дава грешка

  3. MySql заявка за текуща корекция на баланса

  4. Mysql - Предотвратяване на дублиращи се записи на комбинирани колони с уникален индекс

  5. Избиране на MySQL с условие CONCAT