2

我有一个需要“简单”家谱的应用程序。我希望能够执行查询,给我一个来自家庭成员的 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 将获取母亲和父亲的结果,以及他们的母亲和父亲,依此类推。这条路线的问题是数据位于嵌套数组中,我不确定如何有效地处理代码。

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

4

1 回答 1

2

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

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

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

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

  • 添加一些没有家庭的人

这也是相当可行的: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示例,以更实用的颜色显示。)

于 2012-07-07T09:00:43.207 回答