【问题标题】:Database Normalization design Issue: 2 tables sharing almost the same information数据库规范化设计问题:2 个表共享几乎相同的信息
【发布时间】:2012-11-17 16:14:51
【问题描述】:

示例场景假设我的产品公司只有两种类型的买家。

买家 1:个人买家

买家 2:公司买家

买家 1 的独特之处属性:FName、LName、Bdate 和 Age

Buyer 2 的独特之处属性:Company_Name、Nature_Of_Business 和 Type_Of_Business

共同对于 2 个买家是:地址、电子邮件、电话号码、国家/地区

 Db Table Name: Buyer
 Attributes: BuyerID, BuyerType **FName,LName,Bdate,Age**,Company_Name, Nature_Of_Business and Type_Of_Business

我的解释:如果您尝试查看表格买家,个人买家和公司买家的属性都被合并,因为他们都是买家,他们只是根据买家类型(个人或公司)进行分类

问题:如果买家类型是公司,那么我的个人属性(即 FName、LName 等)将被记录为空,反之亦然。我的想法阻止我将它们分开,因为我不想为每个表创建买方 ID。无论是个人还是公司,它们都应该只有 1 个买方 ID。

问题:如何构造数据库表来解决这个查询:

我想要显示所有买家信息且没有空记录的报告。

听起来很疯狂,但当可能生成报告时,如果买家类型为公司,详细信息可能会给出个人买家字段的空记录

注意:如果我将过滤特定的买家类型,这可以轻松完成,但事实并非如此。我都想要。

【问题讨论】:

  • 对不起,我不太明白:I DON'T want to create Buyer's ID for each table。买家可以是个人和公司,还是应该只是其中之一?也许这个answer 可以帮助你。
  • @MostyMostacho 这意味着通过为个人买家和公司买家创建2个单独的表格,这将导致买家ID重复,因为他们都是买家。谢谢
  • 他们不会被复制,因为他们将是不同的买家,他们完全可以不同。不过你没有回答我的问题:)
  • @MostyMostacho 抱歉,我的英语不太好。所以你的意思是可以构建 2 个表购买者(个人和公司)?如果是这样,最接近的可能性是个人买家拥有 ID #1,而公司买家也拥有 ID #1。您如何在报告中协调这一点?
  • 嗯,我不明白他们为什么要和解。他们应该一起被喜欢吗?如果是这种情况,那么我将创建一个“抽象买家”表,然后为其他每个表创建一个。当然,每个表都会有自己的 ID,并且会有所不同。你所说的reconciliation 只是一个外键,它将每个子表链接到父表。只需一个简单的inner join 就足够了 :) 检查我提供的链接,我已经清楚地解释了如何做到这一点。

标签: mysql database oracle database-design relational-database


【解决方案1】:

您可以根据出生日期计算年龄,因此无需存储年龄。

您有一个买家表以及单独的个人买家和公司买家表。

Buyer
------
Buyer ID
Buyer Type
Buyer Type ID
Address
Country
Email
Telephone Number

Individual Buyer
----------------
Individual Buyer ID
Last Name
First Name
Birth Date

Company Buyer
-------------
Company Buyer ID
Company Name
Type of Business
Nature of Business

买家类型是指向该买家的特定子表的指标。 'I' 代表个人,'C' 代表公司将是定义指标的一种方式。

买家类型 ID 是个人买家 ID 或公司买家 ID 的外键。

获取所有买家信息的 SQL 是

SELECT *
FROM Buyer, "Individual Buyer", "Company Buyer"
WHERE "Buyer ID" = 12345
  AND (("Buyer Type ID" = "Individual Buyer ID") AND ("Buyer Type" = 'I'))
   OR (("Buyer Type ID" = "Company Buyer ID") AND ("Buyer Type" = 'C'))

如果您想要多个买家行,请调整 WHERE 子句。

【讨论】:

  • 谢谢。我会将此视为一种解决方案,但会用样本数据进行试验,以便彻底测试它。对此,我真的非常感激。我担心的是在生成报告期间。
  • 我想我想问一下关于表连接的问题。当我想查询将列出来自“个人”和“公司”的买家记录及其相应的个人信息的买家表时,这是如何工作的?因为当我基本上加入表格时,我只能从“个人”和“公司”获取 ID,但很难从个人表以及 Company_Name 和 Nature_Of_Business 中获取 First_Name 和 Last_Name。我现在正在做报告,但已经花了 2 天时间来分析并回复您,也许您仍然可以回答我的报告问题。
  • 非常感谢。我真的很感谢你的帮助。很好的开始。我成功地得到了我需要的东西,但没有错误我收到警告:“未知的表状态:TABLE_TYPE”。不是很必要,但如果你知道这意味着什么,可能会告诉我。非常感谢吉尔伯特爵士。
  • 哦,对不起,。我刚刚发现了。需要输入 SELECT Buyer.*、Individual_Buyer.*、Company_Buyer.* 而不仅仅是 SELECT * 以避免警告。
【解决方案2】:

您的 逻辑 架构可能具有三个不同的实体:一个包含所有公共字段的抽象采购商,以及从它继承的两个子实体:个人采购商和公司采购商。

如何在物理上实现该架构取决于您。通常,共享相同主键(此处为buyerID)的所有逻辑实体将合并到同一个物理表中。

有一个表是有意义的:

  • 性能的角度来看:过滤比加入一般占用更少的资源。使用单个表的 DML 也会快得多。

  • 完整性的角度来看:当您有多个表时,很容易插入无效数据。例如,如果您有三张表,则很难保证买方 ID 在子实体中至少一行且至多一行。

我会选择一个有约束的物理表:

CREATE TABLE buyer (BuyerID primary key, BuyerType, 
                    FName,LName,Bdate,
                    Company_Name, Nature_Of_Business, Type_Of_Business,
                    CONSTRAINT individual_chk 
                       CHECK (BuyerType = 2 OR (Company_name IS NULL AND
                                                Nature_Of_Business IS NULL AND
                                                Type_Of_Business IS NULL)
                              ),
                    CONSTRAINT company_chk
                       CHECK (BuyerType = 1 OR (...))
                   )

检查约束还将验证每种类型的必填字段不为空。

如果您需要分别访问个人和企业,则可以创建视图:

CREATE VIEW individual_buyer IS 
   SELECT BuyerID, 
          FName,LName,Bdate
     FROM buyer 
    WHERE buyerType = 1

CREATE VIEW company_buyer IS 
   SELECT BuyerID, 
          Company_Name, Nature_Of_Business, Type_Of_Business
     FROM buyer 
    WHERE buyerType = 2

【讨论】:

    猜你喜欢
    • 2011-04-18
    • 2023-03-23
    • 2011-11-20
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 2011-12-20
    • 2011-11-04
    相关资源
    最近更新 更多