Agus Darmaputra
Agus Darmaputra

Reputation: 33

MySQL SUM with same ID

Sorry for the real simple question, I just learn PHP & MySQL, I already googling it for more than a week but I didn't found any answer.

I create a simple finance script and the table is like below :

table_a
aid | value
1   | 100
2   | 50
3   | 150

table_b
bid | aid | value
1   | 1   | 10
2   | 1   | 15
3   | 2   | 5
4   | 2   | 10
5   | 3   | 25
6   | 3   | 40

I want the result like this

No | ID | Total | Balance
1  | 1  | 10    | 90
2  | 1  | 25    | 75
3  | 2  | 5     | 45
4  | 2  | 15    | 35
5  | 3  | 25    | 125
6  | 3  | 65    | 85

Can anybody help me with my problem?

Thanks

Upvotes: 3

Views: 4712

Answers (3)

Quassnoi
Quassnoi

Reputation: 425301

You are looking for analytics functions. Unfortunately, MySQL lacks them.

You can implement it in a less efficient way:

SELECT  bid, aid, total, value - total
FROM    (
        SELECT  b.bid, b.aid, COALESCE(a.value, 0) AS value,
                (
                SELECT  SUM(value)
                FROM    b bp
                WHERE   bp.aid = b.aid
                        AND bp.bid <= b.bid
                ) AS total
        FROM    b
        LEFT JOIN
                a
        ON      a.aid = b.aid
        ) q

Upvotes: 0

Michael Buen
Michael Buen

Reputation: 39393

Try this running total: http://www.sqlfiddle.com/#!2/ce765/1

select  
    bid as no, value,
    @rt := if(aid = @last_id, @rt + value, value) as total,
    @last_id := aid
from table_b b, (select @rt := 0 as x, @last_id := null) as vars
order by b.bid, b.aid;

Output:

| NO | VALUE | TOTAL | @LAST_ID := AID |
|----|-------|-------|-----------------|
|  1 |    10 |    10 |               1 |
|  2 |    15 |    25 |               1 |
|  3 |     5 |     5 |               2 |
|  4 |    10 |    15 |               2 |
|  5 |    25 |    25 |               3 |
|  6 |    40 |    65 |               3 |

Then join to table A, final query:

select x.no, x.aid, x.value, x.total, a.value - x.total as balance
from
(
  select    
    bid as no, aid, value,
    @rt := if(aid = @last_id, @rt + value, value) as total,
    @last_id := aid
  from table_b b, (select @rt := 0 as x, @last_id := null) as vars
  order by b.bid, b.aid
) as x
join table_a a using(aid)

Output:

| NO | AID | VALUE | TOTAL | BALANCE |
|----|-----|-------|-------|---------|
|  1 |   1 |    10 |    10 |      90 |
|  2 |   1 |    15 |    25 |      75 |
|  3 |   2 |     5 |     5 |      45 |
|  4 |   2 |    10 |    15 |      35 |
|  5 |   3 |    25 |    25 |     125 |
|  6 |   3 |    40 |    65 |      85 |

Live test: http://www.sqlfiddle.com/#!2/ce765/1


UPDATE

Not dependent on column bid sorting, running total on grouping will not be impacted: http://www.sqlfiddle.com/#!2/6a1e6/3

select x.no, x.aid, x.value, x.total, a.value - x.total as balance
from
(
  select    
    @rn := @rn + 1 as no, aid, value,
    @rt := if(aid = @last_id, @rt + value, value) as total,
    @last_id := aid
  from table_b b, (select @rt := 0 as x, @last_id := null, @rn := 0) as vars
  order by b.aid, b.bid
) as x
join table_a a using(aid)

Output:

| NO | AID | VALUE | TOTAL | BALANCE |
|----|-----|-------|-------|---------|
|  1 |   1 |    10 |    10 |      90 |
|  2 |   1 |    15 |    25 |      75 |
|  3 |   1 |     7 |    32 |      68 |
|  4 |   2 |     5 |     5 |      45 |
|  5 |   2 |    10 |    15 |      35 |
|  6 |   3 |    25 |    25 |     125 |
|  7 |   3 |    40 |    65 |      85 |

Live test: http://www.sqlfiddle.com/#!2/6a1e6/3

Upvotes: 2

Eugen Rieck
Eugen Rieck

Reputation: 65264

SELECT
   tb.bid as No,
   ta.aid as ID,
   tb.value as Total,
   ta.value-tb.total as Balance
FROM
  table_a AS ta
  INNER JOIN (
    SELECT
      tbx.aid AS aid,
      tbx.bid AS bid,
      tbx.value AS value,
      SUM(tby.value) AS total
    FROM 
      table_b AS tbx
      INNER JOIN table_b AS tby ON tby.aid=tbx.aid AND tby.bid<=tbx.bid
    GROUP BY tbx.bid
    ORDER BY tbx.bid
  ) AS tb ON tb.aid=ta.aid
ORDER BY tb.bid

As @Quassnoi pointed out, this is not very efficient with MySQL. I tried to use a freak join instead of a subquery, as the inner query might be of use in its own right.

Edit

Took some interest in this and found the join version to be twice as fast as the subquery version by @Quassnoi ... anybody having an idea why this would be?

Edit

Answer to the second question (in comment below):

SELECT
  table_a.aid AS aid,
  SUM(table_b.value) AS Total,
  table_a.value-SUM(table_b.value) AS Balance
FROM
  table_a
  INNER JOIN table_b ON table_a.aid=table_b.aid
GROUP BY table_a.aid

Upvotes: 1

Related Questions