1

在描述我的问题之前,我想先解决一些问题:

  1. 我是一位经验丰富(虽然不是专家)的数据库设计师。我相信我对关系模型有很好的掌握。
  2. 我对关系模型的理解不够深入,以至于我确切地知道在每种情况下该做什么。我还在学习。

假设我们每月从一家银行获得一次 Excel 电子表格,但并不总是同一家银行。该电子表格只有六列:银行名称、帐号、账户余额、客户(账户持有人)姓名、客户 SSN 和账户持有人地址。每一行都有一个不同的帐号,并且没有帐号被列在多于一行中。我们希望将此电子表格导入数据库,并在未来的任何时候说:“John Smith 2010 年 10 月 13 日的地址是什么?”

为简单起见,假设每个客户只有一个地址,每个客户可以有零个或多个帐户。稍等片刻,让我们假设我们只需要导入一个 Excel 工作表,这是一个愚蠢的前提,但请耐心等待。如果是这样的话,下面的设计就足够了:

bank
--------
id
name

account
--------
id
bank_id
customer_id
number
balance

customer
--------
id
name
ssn
address
city
state_id
zip

state
--------
id
name

我的其余问题基于您同意该架构是“正确”的前提,因此希望您对此感到满意。

现在,如果我们只进行一次导入就可以了,但我们每个银行每年将进行 12 次导入。以下是我考虑的原因:

bank
--------
id
name

account
--------
id
import_id
bank_id
customer_id
number
balance

customer
--------
id
name
ssn
address
city
state_id
zip

state
--------
id
name

import
--------
id
date
excel_file (blob)

现在每个帐户都与导入相关联,我们可以肯定地说“帐户 12345 来自 2010 年 10 月 13 日的导入 572”。customer当您查看例如表格时,它可能会变得更加模棱两可。由于表中的行数少于customer表中的行数account(因为某些客户有多个帐户),因此我们不会像帐户和导入那样在客户和导入之间建立一对一的关系。我知道没有数据丢失,也没有数据完整性的损失,但它仍然感觉像是某种牺牲。

我的问题是(这可能过于开放):您认为这是存储数据的好方法吗?你会做不同的事吗?

编辑:有一种重要的方式来思考这些你必须注意的实体。不要认为account随着时间的推移而存在的单一帐户。将 aaccount视为某个时间点的帐户快照。因此,余额为 100 美元的account账户 12345 与余额为 150 美元的账户 12345 不同。是的,这两条记录都与现实世界中的同一个银行账户相关联,但我存储的是某个时间点的账户快照。与客户类似(但不相同)的情况。

4

6 回答 6

1

抱歉,我无法协调“每个客户只有一个地址”和“我们想说‘约翰·史密斯 2010 年 10 月 13 日的地址是什么’”这两种说法。您是否建议在每次导入时为导入中找到的每个人创建一个新的客户记录?如果是这样,如果帐号不同,您如何知道一次进口中的 John Smith 与另一次进口中的 John Smith 相同?

如果您为同一个客户重复使用相同的客户记录(这对我来说似乎是正确的),您在哪里可以找到以前的地址信息?

[经过发帖人的评论和修改]

好的,你快到了。您确实需要将客户地址添加到 Account 表(实际上应该重命名为 AccountImports 或类似名称)。那是因为每个导入可能有不同的地址。

如果地址从导入到导入经常保持不变,那么将地址存储在 AccountImports 中会有点不正常。如果是这样,您可以添加一个 CustomerAddressHistory 表。在每次导入期间,检查 CustomerAddressHistory 中 SSN 的最新地址,如果与导入不同,则将新地址添加到该表中的新记录中。

于 2010-10-13T19:39:00.897 回答
1

不知道您使用的是什么数据库,但这里是:我不会将导入存储为 a blob,因为它会阻碍您与现有数据链接的能力,因为您必须将其处理blob为您期望的文件类型在您可以将其与您的任何其他数据一起加入之前。将数据与您已有的 id 和日期字段一起直接导入到您的导入表中。放置一个keyon id,然后一个unique compound indexon date、bank 和 account 以防止相同日期的重复。

如果您确定您每年只会有 12 次导入(我猜是几个月?),您可以通过创建两个计算字段来增加完整性,一个用于 date_month(仅保存月份),一个用于 date_year(保存JUST the year),然后创建一个unique compound indexon bank id、account、date_month 和 date_year。这将防止在不同日期意外重新导入同一月的数据,例如,如果 10 月的导入是在周一完成的,那么有人在周二又做了一次。它还可以防止“哎呀,我再次单击按钮”或“哎呀,我将本月的数据作为上个月的数据导入”场景。要加快对计算字段的检查,请在 date_month 和 date_year 上放置唯一索引。

如果您希望您的客户表始终反映当前地址而不大惊小怪,请将地址设置为一个计算字段,该字段通过客户帐户(或 SSN 等)查找您的导入表并选择TOP 1按日期排序的地址DESC。如果您希望对或包含地址字段的查询更快,请在其上放置索引。

于 2010-10-13T20:27:42.793 回答
0

我会谨慎对待客户只有一个地址的想法。(这在我的真实生活经历中是不正确的)。您将需要通过在每次加载时更新客户来存储您获得的最新地址,或者您应该考虑将地址拆分到新表并将其链接到客户 - 可能会显示开始日期和结束日期以显示您何时认为地址是有效的。

我想我也不会把 import_id 放在帐户上。如果你这样做,你会为每个客户到银行的连接获得很多行 (x12)。不是你想要的,我想。相反,您可以放置​​一个帐户到导入链接表,让您知道该帐户已列在这些导入中的一个或多个中。

于 2010-10-13T19:27:22.517 回答
0

我会创建一个名为CustomerAddress的新表,并将地址信息从客户中移出到这个新表中

然后在Account表和CustomerAddress表上添加 2 个新列 StartDateEndDate

这样,您就可以保留一行客户加班时间,并且可以轻松跟踪每个客户帐户和地址加班时间。如果您尝试保留客户的多个副本,则会变得太混乱。

于 2010-10-13T22:59:37.710 回答
0
  1. 由于每次导入都与特定银行相关联,我可能会考虑将 bank_id 放在导入表中并将其从帐户表中删除。
  2. 如果您要考虑历史地址数据,并且仅从导入中获取该数据,则可以将地址字段添加到帐户表中并将它们从客户表中删除。当然,当您有多个进口的相同地址时,这样做可能会导致重复。如果您对此非常关心,您可以添加另一个表,可能是“地址”,可能带有 customer_id 和 address_id 的复合主键。然后,您的导入表添加 address_id 字段,您的导入代码需要检查地址是否已经存在。
于 2010-10-13T19:00:10.150 回答
0

总的来说,设计对我来说看起来不错。

import/import_id 本身除了存储日期之外还有什么意义吗?如果不是,我认为您没有理由不完全排除该表并将 import_date 放在帐户表上。

此外,如果您需要历史地址信息,您还需要 customer 表上的 import_id(或 import_date :))。

更新

如评论中所述,添加 import_id 不会考虑历史地址数据。

您需要的是某种 customer_history 表,它将存储任何可能更改的数据,并通过外键链接回客户表。

customer
------
id
first_name
last_name (assuming name wouldn't change--it certainly could)


customer_history
-----------------
id
customer_id
import_id (or date)
(address fields)

如果帐户的详细信息会随着时间而改变,那么您还需要一个历史记录表。

于 2010-10-13T19:16:45.507 回答