【问题标题】:Database Design: Should I create one table or two for this scenario?数据库设计:我应该为这种情况创建一个表还是两个表?
【发布时间】:2013-10-24 21:39:40
【问题描述】:

场景是时间卡。员工在 TimeCardHeader 表上打卡和打卡,但在 TimeCardDetail 表中输入 Details。但是,他们可以输入至少两种不同的详细信息……这是我的问题。我是创建两个代表每种类型的表格,还是一个带有解释表格含义的布尔标志的表格?

这里是字段(这个例子很小,其他的字段很多):

    Id (PK)
    Version
    StartTime
    EndTime
    LaborDetailDescription
    LaborType: Can be direct or indirect.

如果 LaborType 是 Indirect,则其余字段如下:

    IndirectNumber (FK)

如果 LaborType 是 Direct,则其余字段如下:

    JobNumber (FK)
    JobType
    DirectType: Can be Production or Setup

如果 DirectType 是 Production,则其余字段如下:

    GoodQty
    ScrapQty

如果 DirectType 是设置,则其余字段如下:

    SetupPercent

所以...我是创建一个包含所有这些字段的表,但是当设置类型时,某些字段是空白的(这意味着代码、报告、查询等需要解释数据库),还是做我创建了两个表 DirectLaborDetail 和 IndirectLaborDetail 并将数据整齐地存储到适当的表中?在这种情况下,甚至 DirectLabor 也被分解为 DirectLaborSetup 和 DirectLaborProduction。

我从多个方面提出这个问题:

  1. 根据数据库设计原则的理论纯度。
  2. 性能问题。
  3. 查询创建困难(这也包括针对它的编码)。
  4. 我可能未在此处列出的任何其他注意事项。

编辑:添加了更多细节......

选项 1

/*I intentionally left out the type information*/
CREATE TABLE TimeCardDetail
(
    Id,
    Version,
    TimeCardHeaderId, /*Not depicted here, FK*/
    StartTime,
    EndTime,
    LaborDetailDescription,
    LaborType, /*FK*/
    IndirectId, /*FK*/
    JobId, /*FK*/
    DirectType, /*FK*/
    GoodQty,
    ScrapQty,
    SetupPercent
);

选项 2

CREATE TABLE TimeCardDetail
(
    Id,
    Version,
    StartTime,
    EndTime,
    LaborDetailDescription
);

CREATE TABLE DirectLaborDetail
(
    Id,
    Version,
    TimeCardHeaderId, /*Not depicted here, FK*/
    JobId, /*FK*/
    DirectType, /*FK*/
    GoodQty,
    ScrapQty,
    SetupPercent,
    TimeCardDetailId /*FK*/
);

CREATE TABLE IndirectLaborDetail
(
    Id,
    Version,
    TimeCardHeaderId, /*Not depicted here, FK*/
    IndirectId, /*FK*/
    TimeCardDetailId, /*FK*/
);

作为一个人,我更喜欢这样,因为我可以清楚地看到数据的商业意义,但同时,一切都井然有序,无需解释。查询变得更有趣了,因为如果我想查看特定 TimeCardHeader 的所有详细信息,我需要查看两个表。但这真的是当今计算能力的问题吗?

选项 3

与选项 2 一样,只是我们颠倒了关系...

CREATE TABLE TimeCardDetail
(
    Id,
    Version,
    TimeCardHeaderId, /*Not depicted here, FK*/
    StartTime,
    EndTime,
    Description,
    LaborType, /*FK*/
    FKId, /*would link to the DirectLabordetail or IndirectLaborDetail depending on LaborType*/
);

我没有这个选项,因为 FKId 的含义取决于 LaborType。

【问题讨论】:

    标签: database database-design normalization


    【解决方案1】:

    我会选择一个包含所有列的表,然后其中一些将加载值或在不需要时留空。该解决方案将使您的生活更轻松。

    只有当您认为您将始终分别使用不同的 LaborTypes 查询详细信息时,两个表解决方案才是一个不错的选择,但即使在这种情况下,您也必须决定是否提高性能(两个较小的表更容易处理对于数据库)在开发方面是值得的(插入两个表,查询两个表等)

    关于你的观点:

    1. 理论纯度。不确定是否存在这种情况,但两种方法在理论上都是有效的。实践会告诉您哪种方法最适合您的情况。

    2. 性能。两个表会更小,查询更快,但是你必须维护更多的代码。除非您没有数百万/数十亿行,否则我不会太担心性能。单个表可能会给您带来性能问题,但索引、分区、缓存无论如何都会对您有所帮助。

    3. 查询创建困难。我的建议是这样的表格:

      Id (PK)
      Version
      StartTime
      EndTime
      LaborDetailDescription
      LaborType (FK) 
      IndirectNumber (FK)
      JobNumber (FK)
      JobType
      DirectType (FK) 
      GoodQty
      ScrapQty
      SetupPercent
      

      使用 FK 还可将 LaborType 和 DirectType 用于两个小型查找表,因此您可以在表中仅存储 LaborType_id 和 DirectType_id。同样对于丢失的外键,因为您没有 IndirectNumber for Indirect LaboryType,所以只需创建一个虚拟记录以保持参照完整性。我认为维护一个类似的表应该很简单,你只需要几个 FK 的连接。

    4. 也许可以,但我认为现在开始就足够了

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      相关资源
      最近更新 更多