计算每个类别组的余额

时间:2019-09-12 05:28:44

标签: mysql sql

我有my_table表,其中包含类别组,每个类别都有初始预算(original_budget):

enter image description here

我正在尝试添加一个新列balance,以使其包含每个类别组中的expense中的original_budget减少后的余额。像这样:

enter image description here

我的尝试:

SELECT category, expense, original_budget, (original_budget-expense) AS balance
FROM my_table GROUP BY category order by `trans_date`
  

MySQL版本:innodb_version 5.7.25   10.2.23-MariaDB

2 个答案:

答案 0 :(得分:2)

如果您使用的是MySQL 8+,那么在此处使用SUM作为窗口函数非常简单:

SELECT
    trans_date,
    category,
    expense,
    original_budget,
    original_budget - SUM(expense) OVER
        (PARTITION BY category
         ORDER BY trans_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) balance
FROM my_table
ORDER BY
    category,
    trans_date;

enter image description here

Demo

在MySQL的早期版本中,我们可以尝试使用相关子查询来计算滚动余额:

SELECT
    trans_date,
    category,
    expense,
    original_budget,
    original_budget - (SELECT SUM(t2.expense) FROM my_table t2
                       WHERE t1.category = t2.category AND
                             t2.trans_date <= t1.trans_date) balance
FROM my_table t1
ORDER BY
    category,
    trans_date;

Demo

答案 1 :(得分:1)

对于所有MySQL版本

您可以使用MySQL User defined Variable减少类别的余额。为此,请保留相同类别的记录以及排序日期。

SELECT 
    category, 
    expense, 
    original_budget, 
    IF(@cat <> category, @budg:= original_budget - expense, @budg:= @budg - expense) AS balance,
    @cat:= category -- Set category to current value so we can compare it in next iteration
FROM my_table,
(SELECT @cat:= '' AS c, @budg:= NULL AS b) AS t
ORDER BY category, `trans_date`;


Output:
| category   | expense   | original_budget   | balance   | @cat:= category   |
| A          | 10        | 100               | 90        | A                 |
| A          | 2         | 100               | 88        | A                 |
| A          | 1         | 100               | 87        | A                 |
| B          | 12        | 300               | 288       | B                 |
| B          | 1         | 300               | 287       | B                 |
| B          | 1         | 300               | 286       | B                 |
| B          | 1         | 300               | 285       | B                 |