MySQL算法更新银行交易(最终余额)

Posted

技术标签:

【中文标题】MySQL算法更新银行交易(最终余额)【英文标题】:MySQL algorithm to update bank transaction (final balance) 【发布时间】:2020-12-27 01:47:04 【问题描述】:

我还是 mysql 新手,目前正在解决更新银行交易中最终余额的问题。我首先得到了下表。 The given table named as "transaction"

我预计会给出以下结果; The expected result

我设法通过以下 MySQL 代码处理了 credit_balance 列;


UPDATE transaction 
SET credit_debit = CASE money_in_or_out 
                    WHEN "OUT" THEN amount*(-1)
                    ELSE amount*(1)
                   END;
                   
ALTER TABLE `sql_invoicing`.`transaction` 
CHANGE COLUMN `credit_debit` `credit_debit` DECIMAL(9,2) NULL DEFAULT NULL ;

至于余额一栏,我只管写了以下;

UPDATE transaction 
SET balance = 
(SELECT balance + credit_debit
ORDER BY payment_id DESC
LIMIT 1);

产生以下错误的结果; The returned result

因此,任何人都可以提出任何建议来解决这个问题吗?谢谢!

【问题讨论】:

通常,您会将余额作为帐户表的一部分,而不是作为交易表的一部分。如果您想在每次交易后存储余额,那么我会将其计算为应用程序逻辑的一部分,而不是 sql。基本上是在上一笔交易后取bakance,加上或减去当前交易的值。 @Shadow 嗨,我并不介意账户和交易表(顺便说一句,它只是一个虚拟数据),因为这里的最终目标是让我了解如何编写算法更新银行交易,因为我是 MySQL 新手(刚开始不到 3 周前)。但是,随着我的进步,我会始终牢记这一点。谢谢! 【参考方案1】:

您正在描述一个窗口总和。

首先:我不建议存储此类信息,因为维护起来很繁琐。相反,您可以在需要时即时计算它,或者将逻辑放在视图中。

如果你运行的是 MySQL 8.0,你可以只使用窗口函数:

select t.*,
    sum(case when money_in_or_out = 'OUT' then - amount else amount end) 
        over(order by payment_id) as balance
from transaction t

在早期版本中,您可以改用相关子查询:

select t.*,
    (
        select sum(case when money_in_or_out = 'OUT' then - amount else amount end)
        from transaction t1
        where t1.payment_id <= t.payment_id
    ) as balance
from transaction t

注意:人们可能期望一家银行拥有一个以上的客户。您的表应该有一个列来存储该信息,因此可以每个客户计算余额。然后,您将按如下方式修改窗口函数:

    sum(case when money_in_or_out = 'OUT' then - amount else amount end) 
        over(partition by customer_id order by payment_id) as balance

子查询会变成:

    (
        select sum(case when money_in_or_out = 'OUT' then - amount else amount end)
        from transaction t1
        where t1.customer_id = t.customer_id and t1.payment_id <= t.payment_id
    ) as balance

【讨论】:

不,帐户余额通常是您存储的典型例外情况之一,因为随着时间的推移,每次您想检查是否可以进行交易或客户想查看余额。但是,余额通常存储在帐户表中,而不是交易表中。如果您将其存储在交易表中,它将显示交易后的余额 - 这不会改变,因为如果交易完成,那么它就是最终的。 @Shadow:我明白你的意思。但是,您不认为一个答案比多次 cmet 和 downvotes(假设后者是您的)更有帮助吗?

以上是关于MySQL算法更新银行交易(最终余额)的主要内容,如果未能解决你的问题,请参考以下文章

无法更新双倍(余额)

具有实时余额更新的大容量交易的最佳实践

网上银行安全体系

网上银行安全体系

无法通过类方法更改对象的值

如何在 Google Cloud Datastore 上更新交易中的帐户余额