如何将可以 link 的 table 规范化为一个或多个 table?

How to normalise a table which can link to one or more tables?

我想知道是否有人可以帮助我解决我在尝试为我正在进行的个人项目创建单独的通信 table 时面临的规范化问题。假设我有以下 table 和 table 列:


Table答:

Table_A_Id、日期、姓名、Agent_Id(FK)、备注

代理Table:

Agent_Id、日期、姓名、Phone、电子邮件、备注

直接联系Table

D_C_Id、日期、姓名、Phone、电子邮件、备注


以上是我实际 table 的示例,但描述了我的问题。

基本上要将上面的 table 规范化为 1NF,我需要将 Notes 列拆分成单独的 table,以帮助使 tables 原子化,并遵守1NF 规则。我想把它分成一个单独的列,称为 Communication Table,这样我就可以跟踪我何时进行了与相应 table 相关的对话以及我讨论的内容。

我不确定如何最好地处理拆分出来的 通信 Table。因为 Table A 中的注释也链接到 table 中的代理,但是代理 table 中的注释列仅与代理进行的通信有关。

那么您推荐以下哪一项最适合交流table:

示例 1:

通讯 TABLE

Com_Id、日期、Link_Table、Link_Table_Id、备注

更新:

对不起我忘了,我还需要在上面添加另一个名为Communicated_With的栏目,因为可能存在与Table相关的通信实例A, 可能发生在另一个代理或人身上。

所以 table 看起来像:

Com_Id、日期、Link_Table、Link_Table_Id、Communicated_With、备注

示例 2:

通讯 TABLE

Com_Id、日期、Table_A_Id、Agent_Id、D_C_Id、备注

示例 3:

通讯 TABLE

Com_Id、日期、备注

更新 2

想到了一个新的解决方案,在查看了一些 youtube 视频后,我注意到加入 table 可能会奏效。

示例 4

COMMUNICATION TABLE(与示例 1 相同,没有 "Comminicated_With" 列) Com_Id、日期、Link_Table、Link_Table_Id、Communicated_With、备注

COMM_AGENT_JOIN TABLE com_Id、Agent_Id

抱歉,如果答案很直截了当,我上次做归一化是在 2 年前,因此一直在努力去做。

谢谢。

我会选择存储 Comm_Id、日期、备注的示例 3。我们需要在所有三个父表中添加 Comm_Id 而不是 Notes.

示例 1 和 2 对额外的列执行相同操作(复制信息,也称为 denormalization)。当加入这些表需要更多时间时,我会在查询时使用这些方法。

这不是关于如何将 table 放入 1NF 的答案。不过,我希望它会有所帮助。

在创建数据库时,我们通常不会考虑 1NF、2NF 等。我们会考虑建模什么以及有哪些实体。当我们考虑清楚时,通常数据库已经处于 5NF 左右。如果有疑问,我们可以使用 NF 作为一种检查清单。

我不知道您的确切要求,因此这里有很多猜测或只是一般性建议。也许您的问题之一是您使用的名词 "notes" 并没有准确描述它的含义。后来你叫这个"correspondence",但是都是"notes" = "correspondence"?

您的数据库是关于您直接从代理商或服务公司获得的服务。所以我看到的一个实体是这个提供者:

提供商

  • provider_id
  • 姓名
  • contact_person_name
  • phone
  • 电子邮件
  • 类型(代理或最终服务商)

如果提供商可以有多个联系人、phone 和电子邮件,您可以将其设为 provider_contact table:

提供商

  • provider_id
  • 姓名
  • 类型(代理或最终服务商)

provider_contact

  • provider_contact_id
  • 名字
  • phone
  • 电子邮件
  • provider_id

至于注释:好吧,如果有关于提供者 ("Always ask for Jane; she's the most professional there.") 或联系人 ("Jane has worked in London and Madrid.") 的注释,我通常会将其设为一个文本栏,您可以在其中输入您想要的任何内容像。您甚至可以存储 HTML 或 Word 文档。我想,每个提供者不需要多个文件。

现在也有服务了。要么您需要一份谁提供哪种服务的列表,然后添加这些 tables:service(存在哪些服务)和 provider_service(谁提供哪些服务)。但也许您可以不用它,因为您知道存在哪些服务以及无论如何提供这些服务的人,并且不想在您的模型中使用它。

我不知道你是想输入服务查询还是只输入已经确定的服务合同。在任何情况下,你可能想要一个有或没有状态的 service_contract table。

service_contract

  • service_contract_id
  • provider_id(或者 provider_contact_id?)
  • 服务(自由文本或 service_id 引用服务 table)
  • valid_from
  • valid_to

这里您可能还会有像 "We are still waiting for the documents. Jane said, they will come in March 2018." 这样的注释,这也只是一栏。

然后你说你想要信件,这可能是一个额外的 table service_contract_correspondance:

service_contract_对应关系

  • service_contract_correspondance_id
  • service_contract_id
  • 类型(从提供者处接收或发送给提供者)
  • 文字

但话又说回来,也许你可以没有它。您是否需要访问单个通信(例如 "give me all correspondences from December 2017" 或 "Delete all correspondances older than one year")?或者一份合同上会有数千封信函?也许不是。也许您可以再次将其视为一个文档(文本、HTML、Word 等)并将其作为一个字段添加到 table.

有一个由多个联系人组成的文本,例如

January 2, 2018 Jane
She says they'll need to weeks to make an offer.

January 20, 2018 
I asked about the status. Talked with some Thomas Smith. He says they'll call us tomorrow.

January 21, 2018 Jane
She has emailed the contract for us to sign.

本身并不反对 NF1。只要您对数据库中的详细信息不感兴趣(例如,您永远不会 select 单独在合同上一月份的通信),那么对于数据库来说这是原子的;无需更改。

与联系人相同。如果您有一个仅包含 "Jane (sales person) 123-45678 jane@them.com, Jack (assistent) 123-98765 jack@them.com" 的字符串列,这本身又不是针对 NF1 的。只要你不想只 select 名字或检查 phone 数字,而是始终将字符串视为一个整体,作为 the 联系,那么就可以了这样做。

你看,这一切都归结为你想要建模的内容以及你想要如何处理数据。是的,有代理和直接提供者,但是两者之间的区别大到需要两个不同的table吗?是的,每份合同都有对应的年表,但您真的需要在数据库中将它们分成单独的对应关系吗?