如何最好地将此表模式更改为2或3表模式

时间:2013-06-24 04:11:35

标签: database-design database-schema

我正在从一个非常过时的系统创建/重建新系统,并且正在创建将在新系统中使用的模式。这些表需要一些认真的工作来进行规范化。

我使用的客户表中包含大量重复数据:

  • 有些客户的相关之处在于他们拥有相同的“母公司”。例如,像Graybar Electric这样的供应公司在美国有很多分支机构。在此客户表中,每个分支都列为单独的客户,例如“Graybar Electric - Seattle”。斯波坎的分公司被列为“Graybar Electric - Spokane”。
  • 客户有一个帐单邮寄地址,但帐单邮寄地址可以是一个或多个客户。如果帐单邮寄地址与多个客户相关,则这些客户始终来自同一个“母公司”
  • 但是,母公司的分支机构不一定共享相同的帐单邮寄地址。例如,“Stoneway Electric - Seattle”可能具有与“Stoneway Electric-Everett”不同的帐单地址,但可能与“Stoneway Electric - Tacoma”共享帐单地址。
  • 并非所有客户都是分支机构,他们是他们自己的公司/客户,因此他们没有“母公司”。

以下是我在上面解释的内容的快速视角:

Customer Name        |   Billing Address
--------------------------------------
CustomerA - Branch1  |  BillingAddress1
CustomerA - Branch2  |  BillingAddress1
CustomerA - Branch3  |  BillingAddress2
CustomerA - Branch4  |  BillingAddress3
CustomerB - Branch1  |  BillingAddress4
CustomerB - Branch2  |  BillingAddress4
CustomerC            |  BillingAddress5
CustomerD            |  BillingAddress6
etc....

所以,我想我想要表: ParentCompany 客户 BillingAddress 。但我不确定的是如何将3个表格联系起来。我看到的选择是:

  1. ParentCompany to Customer(1:M),然后Customer to Billing Address(M:1)
  2. ParentCompany to BillingAddress(1:M),然后BillingAddress to Customer(1:M)
  3. 在做出选择时,我试图考虑哪些更容易在带有表单的用户界面中实现。我需要考虑:

    • 为现有母公司添加客户分支
    • 为尚不存在的母公司添加客户分支。
    • 添加不是母公司分支的客户。
    • 添加分支客户时,用户会选择与母公司相关的现有帐单邮寄地址,或输入新的帐单邮寄地址。
    • 现有的单个客户希望添加分支客户,因此现在新客户和原始单个客户都需要与新的母公司相关联。

    所以我的问题是:

    1. 哪种架构最适合我的情况?
    2. 我需要考虑上述每个选项的优缺点吗?
    3. 我还缺少其他选项或考虑因素吗?
    4. 感谢您的意见。

1 个答案:

答案 0 :(得分:0)

  

所以,我想我想要表: ParentCompany 客户 BillingAddress 。但我不确定的是如何将3张桌子联系起来。

你正在倒退。

您有客户。其中一些客户有母公司。

每家公司都有一个帐单邮寄地址。许多公司可能会共享帐单地址。

让我们从客户和帐单地址开始。

Customer
--------
Customer ID
Customer Name
Billing Address ID
...

Billing Address
---------------
Billing Address ID
Billing Address Line 1
Billing Address Line 2
Billing Address City
Billing Address State
Billing Address Zip
... 

现在,当我们介绍母公司时会发生什么?我们不希望更改客户与帐单邮寄地址之间的关系。由于并非每家公司都有母公司,因此我们将母公司作为客户的子类。

Parent Company
--------------
Parent Company ID
Parent Company Name
...

Parent Company / Customer
-------------------------
Customer ID
Parent Company ID
Billing Address ID

关系表的关键是所有3个ID字段。如果您想通过父公司ID或帐单地址ID获取关系,则可以使用其他唯一密钥。

让我们测试一下这个架构。

  

为现有母公司添加客户分支

在Customer表中添加一行,在Parent Company / Customer表中添加一行。 Parent Company / Customer表中的帐单邮寄地址ID取代Customer表中的帐单邮寄地址ID。您的应用程序代码需要确保这一点。

  

为尚不存在的母公司添加客户分支。

在Parent Company表中添加一行。在Customer表中添加一行。在Parent Company / Customer表中添加一行。

  

添加不是母公司分支的客户。

在Customer表中添加一行。

  

添加分支客户时,用户会选择与母公司相关的现有帐单邮寄地址,或输入新的帐单邮寄地址。

这是与GUI相关的问题,但您从父公司/客户表中选择母公司的所有帐单地址,用户可以选择一个或输入新的帐单邮寄地址。您需要在父公司/客户表上使用唯一索引(父公司ID,账单地址ID,客户ID)才能使选择有效。

  

现有的单个客户希望添加分支客户,因此现在新客户和原始单个客户都需要与新的母公司相关联。

添加Customer表行。添加父公司表行。将两行添加到Parent Company / Customer表以进行关联。如有必要,请更新Customer表上的原始客户行。

祝您的数据库修订顺利。

编辑回答评论中的问题。

  

您能否详细说明母公司/客户表?该表是否属于Customer和Parent Company表之间的关系?

此表关联母公司和客户。维基百科称之为junction table。存在将母公司和客户联系在一起。

  

3张桌子之间的基数是多少?

每个母公司/客户关联的父公司/客户表上都会有一行。

  

另外,请您详细说明您的陈述:“关系表的关键是所有3个ID字段。如果您想通过父公司ID或帐单地址ID获取关系,您可以拥有其他唯一密钥“还有其他要考虑的关键吗?

我用单词key来表示索引。对不起,如果这让你感到困惑。

主要(群集)索引是(客户ID,母公司ID,帐单地址ID)。

您还需要一个唯一索引(父公司ID,账单地址ID,客户ID),用于您概述的GUI地址屏幕。

根据您要查询的其他内容,您需要其他唯一索引。

您可以定义另外4个唯一索引。可以从3个关键列中创建6个唯一索引。这称为Cartesian product

如果父公司/客户表上的SQL选择运行速度很慢,请查看where子句。这通常表示您需要在表上使用新索引,而where子句显示要在索引中放入哪些列。

最后,这是一个问题的答案。这不是教程。我无法牵着你,指导你完成数据建模的研究。我建议你研究一下database normalization上的维基百科文章。