【问题标题】:One To Many To Itself一对多对自己
【发布时间】:2010-09-14 16:01:11
【问题描述】:

如何为与自身具有一对多关系的实体构建表?具体来说,我正在开发一个跟踪动物繁殖的应用程序。每只动物都有一个ID;它还有一个父亲身份证和一个女士身份证。因此,从父系或母系到其后代,有可能是一对多的。我会倾向于这样的事情:

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT 
DAME_ID INT

并为那些购买并添加到种畜中的动物记录一个空值,并在表格中为其余的记录一个 ID。

所以:

  1. 谁能给我指一个 讨论的文章/网页 建模这种关系?
  2. ID 应该是 INT 还是某种类型 字符串? INT 中的 NULL 将 表示该动物没有 数据库中的父母,但一个字符串 具有特殊标志值的可能是 用于表示相同的事物。
  3. 这可能是最好的建模吗 通过两张桌子?我的意思是一张桌子 为动物和一个单独的 仅表明亲属关系的表格 e. g.:

    动物

    ID INT NOT NULL PRIMARY KEY

    亲属关系

    ID INT NOT NULL PRIMARY KEY FOREIGN KEY

    SIRE_ID INT PRIMARY KEY FOREIGN KEY

    DAME_ID INT PRIMARY KEY FOREIGN KEY

我为上述情况道歉:我的 SQL 生锈了。我希望它能表达我的想法。

【问题讨论】:

  • 如果您使用的是 Oracle,请查找有关 connect_path 的信息。它是 sql 的扩展,允许进行“分层查询”,在 1 个查询中检索您想要的关系所喜欢的所有后代或祖先。

标签: database-design data-modeling table-structure


【解决方案1】:

嗯,这是一种“正常”的一对多关系,您建议的方法是解决它的经典方法。

请注意,两个表是非规范化的(我无法准确指出 superkey-is-not-well-should-be-subset-of-other-key-fsck-I-forgot 部分在哪里,但我我很确定它在某个地方);直观的原因是第一个中的一个元组最多匹配第二个中的一个元组,所以除非你有很多动物的父亲和贵妇人 ID 为空,否则它在任何前景中都不是一个好的解决方案(它会降低性能 - 需要一个连接——并且不会减少存储需求)。

【讨论】:

  • 非常感谢——这正是我希望得到的。
  • 规范化表格,至少3个第一,说说使用正确的表和正确的pk。 a) 避免将具有自身功能依赖的列子集合并到更大的表中 (2NF) b) 避免与 pk 的传递关系。请注意,这里并非如此,所以它是完美的。
  • 我很确定这算作传递性的退化案例。
【解决方案2】:

我认为您只使用一张桌子的布局很好。您肯定希望将 SIRE_ID 和 DAME_ID 保持在与 ID 相同的数据类型中。您还希望将它们声明为 FOREIGN KEY(可以有一个外键指向同一个表,并且外键也可以为空)。

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT REFERENCES TABLENAME (ID)
DAME_ID INT REFERENCES TABLENAME (ID)

使用这种布局,您可以轻松查找父动物,还可以为给定动物构建后代树(对于 Oracle,有 CONNECT BY)

【讨论】:

    【解决方案3】:

    几个月前,我在 MySQL 网站上问了一个类似的问题。我建议你看看我从 Peter Brawley 那里收到的关于这种关系的回复:http://forums.mysql.com/read.php?135,187196,187196#msg-187196

    如果您想进一步研究该主题,那么我建议您查看 Wikipedia 上的 Tree Hierarchies。

    另一种建议的架构(将完全标准化)如下所示:

    表格:动物

    ID |姓名 |品种

    表:系谱

    animal_id | parent_id | parentType(父亲或母亲)

    【讨论】:

    • @gabriel1836,感谢您的链接——这正是我正在寻找的东西。
    • 表谱系也可以旧其他有趣的数据,如授精日期等...
    【解决方案4】:

    INT 是 ID 列的更好选择,如果您应该使用序列来生成唯一 ID,则更适合。

    我认为将设计拆分为两个表没有任何好处。

    【讨论】:

    • 将设计拆分为两个表的好处只是规范了数据结构。它通常允许最佳地使用 SQL 功能。
    【解决方案5】:

    我不知道动物繁殖,但听起来您的 Sire_ID 是父亲,而 Dame_ID 是母亲?没问题。每只动物一行,对于购买的动物,seire_ 和 dame_ID 为空,我认为没有任何问题。

    [ID],[Sire_ID],[Dame_ID];
    0,null,null  (male)
    1,null,null  (female)
    2,null,null  (female)
    3,0,1 (male)
    4,0,2 (male)
    5,null,null  (female)
    6,3,5
    7,4,5
    

    等等。您可能会在 while 循环中填充 TreeView 或 XmlNodeList...

    While (myAnimal.HasChildren) {
     Animal[] children = GetChildren(Animal.ID)
     for (int x=0; x<children.length; x++) 
      myAnimal.Children.Add(children[x]);
    }
    

    在这种情况下,Animal.Children 是动物的集合。因此,myAnimal.Children[0].Father 将返回 myAnimal。 .Parent[] 可以是它的两个父母的集合,只要 [0] 始终是一个父母(父亲)并且 [1] 始终是另一个父母(母亲),它就应该工作。

    使 ID 成为自动编号 PK,并通过返回其父母的 ID 以编程方式分配 Sire_ID 和 Dame_ID。不需要外键关系,但如果您确实需要,两个父 ID 都可以引用回 ID。

    【讨论】:

      【解决方案6】:

      在 SQL 中使用“connect by”子句来告诉它要遵循哪个层次结构。

      【讨论】:

        【解决方案7】:

        这并不是真正的一对多关系,除非动物可以有多个父母。

        我会将其保留为一个单独的表格,其中包含动物的唯一键 ID、每个父母的一个 int 字段,以及可能用于有关动物的一般说明的文本字段,例如购买地点案例。

        【讨论】:

        • 你看错了。一个父母对许多后代。 :-)
        【解决方案8】:

        我认为,既然很明显一种动物只有一个父亲和一个母亲,那么使用一张桌子是最有意义的。我的偏好是使用 int 或 bigint 作为行标识符,空值表示没有关系。那么,我可能会使用其他方法来唯一标识动物,这样它们就不会在表中出现两次,并且也会在该列上创建一个唯一索引。

        【讨论】:

          【解决方案9】:

          好像你想建树之类的东西。

          类似的东西呢?:

           ID          Primary Key,
           Parent_ID   Foreing_Key
           ( data )
          

          有一些功能可以在与自身有关系的表中进行查询。查看Connect By的语法:http://www.adp-gmbh.ch/ora/sql/connect_by.html

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多