我目前将金融交易存储在下表中(为简洁起见而缩短):
id INT
start DATETIME
end DATETIME
rate INT
usage INT
usage_fee INT
amount INT
commission_pct INT
payout INT
currency VARCHAR(5)
向客户收取的总金额计算如下:
amount = (end - start) * rate + usage * usage_fee
该平台收取以下费用/佣金:
commission = amount * (commission_pct / 100)
服务提供商收到的付款是:
payout = amount - commission
现在在上表中,存储支出在技术上是多余的,因为它可以如上所示计算。我的问题是,关于数据冗余存储这些类型的金融交易的常用方式/约定是什么?
例如,除了它们的总和(金额)之外,我还考虑将(end - start) * rate
和的结果单独存储在此表中。usage * usage_fee
我看到这样做的优点是:
- 将相应金额发送到“支付提供商的 API”时没有(舍入)错误,即用户最终支付的金额与存储在数据库中的金额完全相同,而不是将计算值发送到所述 API
- 易于查询和分析
这些专业人士是否有效,或者您会建议我完全规范化表格并在需要时计算值?
我知道根据“数据库设计原则”对表格进行规范化是正确的答案,但由于我正在处理财务数据,我不确定我是否 100% 满意使用计算值。
每笔交易的佣金率并不具体,但收取的佣金百分比将来很可能会发生变化,因此它与每笔交易一起存储。当然,如果存储实际的“佣金金额”,则无需存储佣金百分比。
那个时间点使用的commission_pct 和rate 存储在表中,这就是为什么将来为后续交易更改这些不是问题并且永远不会编辑现有交易的原因。此外,只有一个受控应用程序可以访问数据库。如果将来公式发生变化,不计算和存储结果将是一个问题。我倾向于应用程序计算这些值并一举存储“原始”值和计算值。
像这样存储计算结果是很常见的,因此您记录的是金融交易的事实,而不是您认为应该发生的事情。还因为存储结果允许您随时间执行调整和更改计算。
存储支出的一个可能问题是它的计算位置和方式。看起来它将在插入事务的应用程序中完成。
是什么阻止任何有权访问该表的人在不计算支出的情况下插入交易?如果应用程序更新交易,例如更改费率或佣金 pct 怎么办?存储的支出将不正确。
一些数据库可以使用应用程序权限来防止这种情况,即只有拥有更新表权限的应用程序才能这样做。
存在不存储计算的支出的解决方案,但存在每个需要支出的人都必须计算它的问题。这意味着所有人都必须为此使用相同的公式。改变公式意味着改变所有这些应用程序——如果你都知道的话。
要么存储支出并通过触发器自动计算,要么将其设为
VIRTUAL
自动计算的列(并且不需要存储)。——阿尔伯特·戈德芬德