1

I need to show the running total for each person in my database but I could only get the running total for all of them, so these are my tables on the pic

I already have this query:

SELECT 
    id, 
    studno,
    if(type=0,amount,0)debit,
    if(type=1,amount,0)credit,
    if(type=0,@bal:=@bal+amount,@bal:=@bal-amount) runningTotal
FROM
(SELECT id, studno, amount, 0 type from tblPayables 
UNION ALL 
SELECT id, studno, amount, 1 type from tblPayments)s, (SELECT @bal:=0)b
ORDER BY studno, id, type;

but the thing is I can only come up to this result:

The highlighted number should be 50 since it's for a different studno

adrianbanks
  • 81,306
  • 22
  • 176
  • 206

2 Answers2

2

You must write your query in such a way that the variable is initialized every time an Id changes.

Let's say you can write a query or view with the following columns:

id | studno | debit | credit
---+--------+-------+-------

So, let's write the query:

select id, debit, credit
     , @bal := ( -- If the value of the column `studno` is the same as the
                 -- previous row, @bal is increased / decreased;
                 -- otherwise, @bal is reinitialized
         case 
             when @studno = studno then @bal + debit - credit
             else debit - credit
         end
     ) as balance
     @studno := a.studno as studno -- It's important to update @studno
                                   -- AFTER you update @bal
from 
    (
        select @bal := 0
             , @studno := 0 -- This variable will hold the previous
                            -- value of the `studno` column
    ) as init, -- You must initialize the variables
    ( -- The above mentioned query or view
        select ...
        from ...
    ) as a
order by a.studno, a.id -- It's REALLY important to sort the rows
Barranka
  • 20,547
  • 13
  • 65
  • 83
  • thank you so much but how can I hide the @studno:=studno column? – Bernadine Bacolod Feb 12 '15 at 23:38
  • @BernadineBacolod See my updated answer (I removed the first `studno`, and put it as the last column. It's important to update `@studno` *after* `@bal`, because otherwise the running total won't work – Barranka Feb 12 '15 at 23:44
  • @BernadineBacolod [Check this question and it's answers](http://stackoverflow.com/questions/17664436/cumulative-sum-over-a-set-of-rows-in-mysql) – Barranka Feb 13 '15 at 00:09
0

as I wrote in comments - existing query does interleaving wrong, it will fail if payment id for corresponding payable id is smaller

here is query which does interleaving properly and calculate running total as @Barranka suggested:

select studno, amount, @bal := (
         case 
             when @studno = studno then @bal + amount
             else amount
         end
     ) as balance,
  @studno := studno
from
(
        select @bal := 0
             , @studno := 0
) as init,
(
select 0 as t, studno, amount, (select count(*) from tblPayables as b where a.id>b.id and a.studno=b.studno) as trN
from tblPayables as a
union all
select 1 as t, studno, -amount, (select count(*) from tblPayments as b where a.id>b.id and a.studno=b.studno) as trN
from tblPayments as a
) as q
order by studno, trN, t

http://sqlfiddle.com/#!2/9e0cf1/1

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57