数据库设计:我应该为这种情况创建一个或两个表吗?

时间:2013-10-24 12:19:44

标签: database database-design normalization

场景是时间卡。员工在TimeCardHeader表上输入并输出,但在TimeCardDetail表中输入Details。但是,他们可以输入至少两种不同的细节......这是我的问题。我是否创建了两个表示每种类型的表,或者是一个带有布尔标志的表来解释表的含义?

以下是字段(此示例很小,其他字段有很多字段):

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

如果LaborType为间接,则其余字段为:

    IndirectNumber (FK)

如果LaborType为Direct,则其余字段为:

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

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

    GoodQty
    ScrapQty

如果DirectType是Setup,则其余字段为:

    SetupPercent

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

我在很多方面都在问这个问题:

  1. 根据数据库设计原则的理论纯度。
  2. 表现问题。
  3. 查询创建困难(这也包括编码)。
  4. 我在此处未列出的任何其他考虑因素。
  5. 编辑:添加了更多细节......

    选项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的含义。

1 个答案:

答案 0 :(得分:1)

我会选择包含所有列的单个表,然后其中一些将加载值,如果不需要则保留为空。此解决方案将使您的生活更轻松。

只有当您认为您将始终单独查询具有不同LaborType的详细信息时,两个表解决方案才是一个不错的选择,但即使在这种情况下,您还必须确定性能的提升(两个较小的表更容易处理)对于db)在开发方面是值得的(在两个表中插入,查询两个表等)

关于你的观点:

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

  2. 性能。两个表将更小,查询速度更快,但您必须维护更多代码。在你没有数百亿/数十亿行之前,我不会过分担心性能问题。单个表可以解决性能问题,但索引,分区和缓存无论如何都会对您有所帮助。

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

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

    对于LaborType和DirectType,FK也有两个小的查找表,因此您只能在表中存储LaborType_id和DirectType_id。此外,对于缺少的外键,因为您没有IndirectNumber for Indirect LaboryType,只需创建一个虚拟记录以保持参照完整性。我认为维护类似的表应该非常简单,你只需要为FK提供几个连接。

  4. 也许,但我认为现在已经足够开始了