使用mysql或更好的algothrim匹配借记卡和每笔交易的贷方?

首先让我解释一下表结构和我所需的输出.

userid  date           amount 
123    2017-01-01         5 
123    2017-01-03         2 
124    2017-01-04         2 
124    2017-01-04         3 
123    2017-01-05         -2

借方交易是负面的,正面交易是会员的信用交易.
我们可以通过此查询轻松完成帐户对帐单

select date as BookingDate,
       if(amount<0,amount,0) as Debit_Amount,
       if(amount>0,amount,0) as Credit_Amount,
       (@runtot :=  amount  + @runtot) AS Balance  
from transactions,
     (SELECT @runtot:=0) c 
where userid=123


BookingDate  Debit_Amount  Credit_Amount  Balance 
2017-01-01    0                 5           5 
2017-01-03    0                 2           7 
2017-01-05   -2                0           5

我的要求是使用FIFO方法标记每笔支付或部分支付的交易.像这样.这可能通过mysql查询或更好的算法?

 userid  date           amount   status
    123    2017-01-01         5   partial_paid(-2)
    123    2017-01-03         2 
    124    2017-01-04         2 
    124    2017-01-04         3 
    123    2017-01-05         -2

谢谢

最佳答案

MariaDB [sandbox]> create table t(userid  int,dt date,  amount int);
Query OK, 0 rows affected (0.28 sec)

MariaDB [sandbox]> truncate table t;
Query OK, 0 rows affected (0.20 sec)

MariaDB [sandbox]> insert into t values
    -> (123  ,  '2017-01-01'  ,       5) ,
    -> (123  ,  '2017-01-03'  ,       2 ),
    -> (124  ,  '2017-01-04'  ,       2) ,
    -> (124  ,  '2017-01-04'  ,       3 ),
    -> (123  ,  '2017-01-05'  ,       -2),
    -> (125  ,  '2017-01-01'  ,       5) ,
    -> (125  ,  '2017-01-03'  ,       2 ),
    -> (125  ,  '2017-01-05'  ,       -6),
    -> (126  ,  '2017-01-01'  ,       5) ,
    -> (126  ,  '2017-01-02'  ,       -10),
    -> (126  ,  '2017-01-03'  ,       2 ),
    -> (126  ,  '2017-01-05'  ,       -10),
    -> (126  ,  '2017-01-06'  ,       13);
Query OK, 13 rows affected (0.06 sec)
Records: 13  Duplicates: 0  Warnings: 0

MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select s.userid,s.dt,s.amount,
    ->  case when s.crs is null then 0 else s.crs end crs,
    ->  case when s.exhaust is null then 0 else s.exhaust end exhaust,
    ->  case when s.amount > 0 and s.amount <= s.crs and s.crs > 0 then 'Fully paid'
    ->  when s.amount > 0 and s.amount > s.crs and s.crs > 0 then concat('Part paid -' ,s.crs)
    ->  else ''
    ->  end msg
    -> from
    -> (
    -> select t1.*,
    ->  if(t1.userid <> @p ,
    ->   @crs:=(select sum(t2.amount)  * - 1 from t t2 where t2.userid = t1.userid and t2.amount < 0)
    ->   ,@crs:=@crs)  crs,
    ->   if(t1.amount < 0 ,@crs:=@crs,if (t1.amount > @crs , @crs:=0,@crs:=@crs - t1.amount)) exhaust,
    ->   @p:=t1.userid p
    ->
    -> from  (select @p:=0,@crs:=0) p ,t t1
    -> order by t1.userid, t1.dt
    -> ) s
    -> ;
+--------+------------+--------+------+---------+--------------+
| userid | dt         | amount | crs  | exhaust | msg          |
+--------+------------+--------+------+---------+--------------+
|    123 | 2017-01-01 |      5 | 2    | 0       | Part paid -2 |
|    123 | 2017-01-03 |      2 | 0    | 0       |              |
|    123 | 2017-01-05 |     -2 | 0    | 0       |              |
|    124 | 2017-01-04 |      2 | 0    | 0       |              |
|    124 | 2017-01-04 |      3 | 0    | 0       |              |
|    125 | 2017-01-01 |      5 | 6    | 1       | Fully paid   |
|    125 | 2017-01-03 |      2 | 1    | 0       | Part paid -1 |
|    125 | 2017-01-05 |     -6 | 0    | 0       |              |
|    126 | 2017-01-01 |      5 | 20   | 15      | Fully paid   |
|    126 | 2017-01-02 |    -10 | 15   | 15      |              |
|    126 | 2017-01-03 |      2 | 15   | 13      | Fully paid   |
|    126 | 2017-01-05 |    -10 | 13   | 13      |              |
|    126 | 2017-01-06 |     13 | 13   | 0       | Fully paid   |
+--------+------------+--------+------+---------+--------------+
13 rows in set (0.03 sec)

当心: – 我还没有完全测试过这个!!

点赞