【问题标题】:Inbreeding-immune database structure近交免疫数据库结构
【发布时间】:2012-07-07 23:50:56
【问题描述】:

我有一个需要“简单”家谱的应用程序。我希望能够执行查询,给我整个家庭的数据,给定来自家庭成员的一个 id。我说简单,因为它不需要考虑采用或任何其他模糊性。申请条件如下:

  • 如果两个人来自同一基因系,他们将无法繁殖
  • 需要允许添加新的家族(没有前世家族的新人)
  • 需要能够通过查询分别拉取兄弟姐妹、父母

我无法为数据库提出正确的结构。到目前为止,我已经提出了两种解决方案,但它们都不是很可靠,并且可能很快就会失控。

解决方案 1 涉及在 people 表中放置一个 family_ids 字段并存储唯一的家庭 ID 列表。每次两个人繁殖时,都会相互检查列表以确保没有 id 匹配,如果所有检查结果都将合并两个列表并将其设置为孩子的 family_ids 字段。

例子:

Father (family_ids: (null)) breeds with Mother (family_ids: (213, 519)) ->
Child (family_ids: (213, 519)) breeds with Random Person (family_ids: (813, 712, 122, 767)) ->
Grandchild (family_ids: (213, 519, 813, 712, 122, 767))

等等等等......我看到的问题是随着时间的推移列表变得不合理地大。

方案二使用 cakephp 的关联声明:

public $belongsTo = array(
    'Father' => array(
        'className' => 'User',
        'foreignKey' => 'father_id'
    ),
    'Mother' => array(
        'className' => 'User',
        'foreignKey' => 'mother_id'
    )
);

现在将 recursive 设置为 2 将获取母亲和父亲的结果,以及他们的母亲和父亲,等等。这条路线的问题是数据在嵌套数组中,我不确定如何有效地处理代码。

如果有人能够引导我以最有效的方式处理我想要实现的目标,那将非常有帮助。非常感谢任何和所有帮助,我很乐意回答任何人的任何问题。非常感谢。

【问题讨论】:

    标签: php mysql cakephp database-design


    【解决方案1】:

    在 SQL(更准确地说,RDBS)中,我会使用以下解决方案:

    1) 创建一个表people,其中包含以下字段 - idnamefather_idmother_id。第一个是典型的主键列,father_id 和 mother_id 引用该列但可以为 NULL(以允许添加新的家族线)。

    2) 创建一个表 relatives,其中包含以下字段 - person_idancestor_id。两者都不为 NULL,都形成复合主键,也都是 person.id 的 FK。

    就是这样。不完全是! ) 现在考虑你的任务:

    • 添加一些没有家族血统的人

    这也很可行:INSERT INTO people (name) VALUES ('some_name')。诀窍是将另一个与这个新人相关的插入到亲戚中: INSERT INTO relatives VALUES (%new_person_id%, %new_person_id%)

    那是为了什么?考虑最常见的任务:添加一些实际上已经在您的表格中列出了父亲和母亲的人。有了这个结构,它就很简单了(在将相应的记录插入people,并得到这个person_id作为结果之后)......

    INSERT INTO relatives 
        SELECT %new_person_id%, ancestor_id 
          FROM relatives 
         WHERE person_id IN (%father_id%, %mother_id%);
    INSERT INTO relatives VALUES (%new_person_id%, %new_person_id%);
    
    • 如果两个人来自同一基因系,他们将无法繁殖。

    使用上面描述的结构,它相当简单:您必须在relatives 中查找在ancestor_id 字段中具有相同值的两条记录。例如:

        SELECT COUNT(*) 
          FROM relatives ra 
    INNER JOIN relatives rb ON ra.ancestor_id = rb.ancestor_id
         WHERE ra.person_id = %person_a_id%
           AND rb.person_id = %person_b_id%
    

    在这个结构中查找所有的祖先和孩子很容易;但我仍然更喜欢去规范化的方法(即,将father_id 和mother_id 存储在第一个表中)以加快直接父母/孩子的查找速度——它实际上可以单独使用第一个表来完成。

    这是一个有效的(虽然有点短)SQL Fiddle 示例,以更实用的颜色显示。 )

    【讨论】:

    • 我还想补充一点(尽管在所有这些写作和摆弄之后,我的一部分人为此对我大喊大叫)你可能会考虑使用面向图形的数据库来完成这项任务。例如,我使用Neo4J 玩得很开心。 )
    • 太好了,非常感谢。这个例子也很有帮助。
    • 是否可以轻松检索仅知道 people.id 的有序树(或某些固定世代:fe.4 或 5)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2023-03-26
    • 2010-11-30
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多