用于跟踪和分摊费用的数据库设计

ban*_*skt 5 mysql database database-design

我想设计一个 Web 应用程序来跟踪组织成员的财务状况。某些功能与Splittr非常相似。我使用 MWE 数据库图表定义我的要求:

  • “财务”表:每个用户将拥有一个个人财务账户,我使用以下三个红色表: 在此处输入图片说明
  • “SharedExpense”表:每个用户可以与许多“共享费用组”中的其他用户共享费用。对于每个组,我使用以下三个蓝色表: 在此处输入图片说明

(注意每个用户如何定义他们的共享金额,以及自己的共享费用类别。UserShare 表使用复合主键。)

问题:我必须将用户与他们的 3 个个人“财务”表和3N“SharedExpense”表(其中N是用户所属的“共享费用组”的数量)相关联。

尝试的解决方案

  1. 多个数据库。每个用户的“财务”表都有一个唯一的数据库。每个“共享费用组”在服务器上都有一个唯一的数据库。然后,我可以将一个主数据库中的用户与以下四个紫色表相关联:
    多数据库解决方案
    缺点:外键来自不同的数据库,需要备份的数据库数量较多。

  2. 多桌。我可以在同一个数据库中创建所有表,并将它们与四个绿色主表相关联: 多表解决方案
    在这里,表的数量是一个潜在的问题。如果有M用户和N“共享费用组”,那么就会有3M + 3N桌子!

问题:是否有更优雅、更简单的数据库设计?如果不是,以上两种解决方案中哪一种更好,为什么?

相关的先前 StackOverflow 问答链接

Wes*_*s H 5

总结中要描述的所有挑战太多了,但我会挑选一些。

  1. 基本设计违规:例如每个用户的表/数据库
  2. 实体设计,3NF:例如category.budget 和ledger.transaction_type
  3. 参照完整性/关系设计:
    • account 是一个用户的,但是 account 表不包含用户 id;
    • usershare 是账本的一个子集,但它们都指向一个用户;
  4. 对象命名关注:
    • 基于实际使用的清晰一致的命名实体。会员是用户还是用户是会员?如果它们相同,请选择一个名称。如果它们不相同,则设计是不同的。员工使用客户还是客户而不是会员?
    • 密钥命名的一致性。键名应直接将其与源实体联系起来。Member.ID 应该被引用为 members_id,而不是 user_id。但是,请在更正之前查看下一个条目。
    • 在你的实体复数中保持一致。普遍的共识是名称应该描述单个记录(用户)而不是所有记录(用户)。
    • ledger.spent_on - 该名称显然不是日期。它也可以指向用户或类别。属性名称应描述该属性,而无需额外解释。例如, ledger.Purchase_Date 是不言自明的。还应该清楚它与实体的关系。UserShare.Share 并没有真正告诉我它包含什么。

恕我直言,但我会重新开始。将您拥有的内容视为良好的试运行,然后使用您拥有的其他信息重新开始。

  • 问你的设计问题(所有用户都是会员吗?所有会员都是用户吗?)。如果答案不是“是”或“否”,请进一步细分。
  • 尝试假设场景(如果共享分类帐超出类别预算怎么办?如果类别预算发生变化,如何看待之前的支出?)
  • 考虑可能会问哪些报告问题(谁超出了预算?我们在这个类别上花费了多少?)然后考虑查询来回答问题。

阅读 3NF,也许还有一些更高的归一化水平。虽然 3NF 几乎是最低规范化,但更高级别变得越来越专业化,可能适合也可能不适合您的设计。

您对数据和业务了解得越透彻,您的设计就会越好,最终产品也会越好。