Database design 单个表的多个外键和指向多个表的单个键

Database design 单个表的多个外键和指向多个表的单个键,database-design,join,foreign-keys,self-join,Database Design,Join,Foreign Keys,Self Join,我需要这里的数据库设计专家提供一些建议 我在一个表中有大约六个外键(缺陷),它们都指向用户表中的主键。就像: defect (.....,assigned_to,created_by,updated_by,closed_by...) 如果我想获得有关缺陷的信息,我可以进行六次连接。我们有更好的办法吗 另一个是我有一个states表,它可以存储用户定义的一组值。我有缺陷表和任务表,我希望这两个表共享公共状态表(新的、进行中的等)。所以我创造了: task(…,state\u id,imp\u

我需要这里的数据库设计专家提供一些建议

  • 我在一个表中有大约六个外键(缺陷),它们都指向用户表中的主键。就像:

    defect (.....,assigned_to,created_by,updated_by,closed_by...)
    
    如果我想获得有关缺陷的信息,我可以进行六次连接。我们有更好的办法吗

  • 另一个是我有一个
    states
    表,它可以存储用户定义的一组值。我有缺陷表和任务表,我希望这两个表共享公共状态表(新的、进行中的等)。所以我创造了:

    • task(…,state\u id,imp\u id,…)
    • defect(…,state\u id,imp\u id…)
    • state(state\u id,state\u name,…)
    • 重要性(imp\u id、imp\u名称等)
  • 有许多这样的公共属性以及状态,如重要性(正常、紧急等)、优先级等。对于所有这些属性,我想使用相同的表。我在每个表中保留一个标志来区分任务和缺陷。在这种情况下,最好的解决方案是什么


    如果有人在健康域中使用此应用程序,他们希望为其缺陷或任务分配不同的类型、状态和重要性。此外,当用户选择任何项目时,我希望在“配置参数”部分下显示所有类型、状态等。

    对于第一个问题,在我看来,您最好将缺陷表分解为一个“行”表,该表存储事务的历史,如创建、更新、分配等

    这样做的好处是更加灵活。缺陷可以更容易地跟踪被更新和分配给多个人、被重新打开等的历史记录,并清楚地表示随着时间的推移多次更新

    您的缺陷表仍将存储缺陷的一些通用全局状态(可能是状态、优先级等,特别是如果您不需要跟踪这些状态的变化),并且您将有一系列*缺陷行*,每个都有一个外键指向缺陷,另一个外键指向用户,以及一个类型字段,指示是否为“创建”、“更新”等

    例如

    根据您的假设,缺陷id、时间戳和用户可能是缺陷行的主键


    对于第二个问题,至少在您提供的信息中,它们似乎共享所有相同的属性——因此基本上是相同的东西,具有不同的类型标志(“任务”或“缺陷”),那么为什么不将它们放在同一个表中呢

    我可能会在假设所有缺陷都可以被视为任务(“需要修复的事情”)的情况下调用此任务,但所有任务都不是缺陷——但现在这只是语义

    如果存在不同的、非共享的属性,那么您可能会遇到这样的情况:您可以在一个表中拥有任务/缺陷的共享属性,以及每个特定属性的表,尽管它们可能仍然能够共享相同的“行”详细结构。这在一定程度上成为规范化和易用性之间的一个决定——拥有两个基本上具有相同属性的表可能更容易,而不是将其分解为多个表

    1

    这本身并没有什么问题。如果可能的用户“角色”是严格确定的,并且不太可能更改,那么实际上,这是最好的方法。您正在有效地建模C:M关系,其中C是常量

    另一方面,如果角色可以更改(例如,您需要能够动态地向缺陷添加新的“生命周期阶段”),则可能需要一个链接(也称为连接)表来模拟真正的M:N关系。大概是这样的:

    顺便说一句,虽然加入有其成本,但这本身并不意味着你负担不起。您甚至可能不需要一直使用所有连接—只需执行连接即可带来您当前需要的信息,而不需要其他信息。在任何情况下,我建议您对实际数据量进行测量,以确定是否存在实际性能问题

    2

    如果有许多公共字段,可以使用inheritance1最小化公共字段和外键的重复。例如:

    在该模型中,每个“属性”表(如
    状态
    重要性
    )只与
    连接一次,并通过它连接到每个“继承”表,如
    缺陷
    任务
    。无论添加多少“继承”表,每个“属性”表都只有一个连接

    该模型从本质上防止了“属性”FK的扩散,因为
    缺陷
    任务
    (因为它们现在被分为“普通”和“特定”部分)的管理有些繁琐。这是否是比旧设计更好的平衡,由您决定



    1又名。类别、子类、泛化层次结构等。

    在这一切中,
    type
    type\u id
    扮演什么角色?类型是状态的属性还是任务或缺陷中状态“实例”的属性?类型基本上是指任务可以具有的重要性(正常、紧急、关键)等,类型_id是该表的主键。现在一个任务和一个缺陷都将有类型(或者更好地称之为重要性)和状态(新的、正在进行中的等等)。布兰科:你太棒了:)我用的是完全相同的桌子结构,所以我现在很有信心我走的方向是正确的。这是我第一次尝试创建端到端应用程序,所以我对表设计有点困惑。
    defect ( id, priority, status )
    defect_line ( defect_id, timestamp, type, user, comment )