Reputation: 33
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
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
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
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