【问题标题】:mysql calculation of balance grouped by datemysql计算按日期分组的余额
【发布时间】:2013-11-17 15:16:52
【问题描述】:

所以让我描述一下我想在这里计算什么。我有 2 个表,在第一个称为余额的表上,每个帐户都有一行及其相应的当前余额。在第二个表上,我有这些帐户的所有存款和取款以及这些存款和取款的确切日期时间发生。我的问题是根据这两张表计算每天所有账户的余额。

1.表余额

|account_id| balance |
|1111      |   1000  |
|2222      |   3500  |
|3333      |   10000 |

2.表信用

account_id|         date      |deposit_withdrawal|
|1111     |2012-11-11 12:35:02|        250       |
|1111     |2012-11-12 18:15:34|        750       |
|1111     |2012-11-12 09:09:04|       -150       |
|2222     |2012-01-12 10:05:04|       1000       |
|2222     |2012-07-15 14:23:04|        -340      |
|2222     |2012-12-29 13:01:04|        450       |

我从信用表中选择账户,获取他们的存款取款总和,然后按 DAYOFYEAR 对其进行分组。现在我被困住了,我无法弄清楚如何计算他们在每个日期的余额。正如我上面提到的,余额表包含账户的当前余额。因此 deposit_withdrawal 表中的最新条目已经记入 balance 表中。

SELECT c.account_id , c.date , SUM(c.deposit_withdrawal)  FROM credit c
JOIN balance b  on b.account_id = c.account_id
GROUP by DAYOFYEAR (c.date)
ORDER BY DAYOFYEAR(c.date) DESC

编辑:谢谢大家的回复,让我再解释一下,假设我们有一个当前余额为 2000 的帐户。在表中他有 3 个条目,1 于 2012 年 10 月 10 日提款300 , 2012 年 11 月 11 日的 1 次,存款 400 和最后一次和最近的一次在 2013 年 2 月 29 日,存款 150。我想做的是找到他之间所有日期的余额2013 年 2 月 29 日和 2012 年 10 月 9 日。我知道在 2013 年 2 月 29 日,这是最近一次,他的余额等于他当前的余额 = 2000。所以前一天,在 2013 年 2 月 28 日,我知道他的余额将是当前余额(2000 年)-最后一次存款 (150) = 1850。直到 2012-11-11 他的余额没有变化。在 2012-11-11 他已经存款 400 ,所以前一天在 2012-11-10 他的余额将是 1850-400 = 1450 等等。

【问题讨论】:

  • 为什么一定要JOIN这两个?每天的余额不会等于总余额
  • “每天所有账户的余额” 这个问题的解决方案是SELECT SUM(balance) FROM balance,所以我想你没有正确地问你的问题。我不知道您的预期最终结果是什么。
  • 我已经编辑了帖子并添加了更新。有人吗?

标签: mysql


【解决方案1】:

您可能应该在添加新记录时将余额存储在贷方表中,这会使事情变得更简单。但是 - 我们可以在没有历史信息的情况下解决这个问题,我们只需要建立某种交易历史。

我们可以通过查看每条信用记录、找到其后的记录并将它们应用于余额来做到这一点:

CREATE TABLE transaction_history (
SELECT
    credit.account_id,
    credit.`date`,
    credit.deposit_withdrawal,
    COALESCE(balance.balance - SUM(next_transactions.deposit_withdrawal), balance.balance) AS balance
FROM
    credit
LEFT JOIN
    credit AS next_transactions
ON
    next_transactions.account_id = credit.account_id
AND
    next_transactions.`date` > credit.`date`
INNER JOIN
    balance
ON
    balance.account_id = credit.account_id
GROUP BY
    credit.account_id,
    credit.`date`,
    credit.deposit_withdrawal
ORDER BY
    credit.`date` DESC
);

这会为我们生成每个信用记录的每个帐户的余额。但要正确使用它,我们需要考虑账户的起始余额:

INSERT INTO transaction_history (account_id, `date`, deposit_withdrawal, balance) (
SELECT
    balance.account_id,
    '0000-00-00 00:00:00',
    0,
    COALESCE(earliest_transaction.balance - earliest_transaction.deposit_withdrawal, balance.balance) AS `balance`
FROM
    balance
LEFT JOIN
    transaction_history AS earliest_transaction
ON
    earliest_transaction.account_id = balance.account_id
AND
    earliest_transaction.`date` = (SELECT MIN(`date`) FROM transaction_history AS te WHERE te.account_id = balance.account_id)
);

这会在应用任何其他交易之前插入时间 0 的记录作为余额,因此账户 1111 有 150,账户 2222 有 2390,账户 3333 有 10000。您最终应该得到如下所示的数据:

mysql> SELECT * FROM transaction_history;
+------------+---------------------+--------------------+---------+
| account_id | date                | deposit_withdrawal | balance |
+------------+---------------------+--------------------+---------+
|       2222 | 2012-12-29 13:01:04 |                450 |    3500 |
|       1111 | 2012-11-12 18:15:34 |                750 |    1000 |
|       1111 | 2012-11-12 09:09:04 |               -150 |     250 |
|       1111 | 2012-11-11 12:35:02 |                250 |     400 |
|       2222 | 2012-07-15 14:23:04 |               -340 |    3050 |
|       2222 | 2012-01-12 10:05:04 |               1000 |    3390 |
|       1111 | 0000-00-00 00:00:00 |                  0 |     150 |
|       2222 | 0000-00-00 00:00:00 |                  0 |    2390 |
|       3333 | 0000-00-00 00:00:00 |                  0 |   10000 |
+------------+---------------------+--------------------+---------+
9 rows in set (0.00 sec)

然后,如果您想在特定日期结束时查找给定帐户的余额,您可以使用以下查询:

SELECT 
    balance 
FROM 
    transaction_history 
WHERE 
    account_id = 1111 
AND 
    `date` <= '2012-11-12 23:59:59'  
ORDER BY 
    `date` DESC 
LIMIT 1;

【讨论】:

  • 非常感谢您的回答!我想这会解决我的问题。
猜你喜欢
  • 2017-07-12
  • 2012-03-12
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 2011-07-21
  • 1970-01-01
相关资源
最近更新 更多