我有一个需要“简单”家谱的应用程序。我希望能够执行查询,这些查询将为整个家庭提供数据,给出一个来自该家庭成员的id。我说的很简单,因为它不需要考虑采用或任何其他晦涩。申请的要求如下:
我无法想出适合数据库的结构。到目前为止,我已经提出了两种解决方案,但它们不是很可靠,很可能会很快失控。
解决方案1涉及在people表上放置family_ids字段并存储唯一的family 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))
依此类推......我看到的问题是随着时间的推移,这些名单变得越来越大。
解决方案2使用cakephp的关联来声明:
public $belongsTo = array(
'Father' => array(
'className' => 'User',
'foreignKey' => 'father_id'
),
'Mother' => array(
'className' => 'User',
'foreignKey' => 'mother_id'
)
);
现在将递归设置为2将获取母亲和父亲以及他们的母亲和父亲的结果,依此类推等等。这条路线的问题是数据是嵌套数组,我不确定如何有效地处理代码。
如果有人能够引导我朝着最有效的方式去处理我想要实现的目标,这将是非常有帮助的。非常感谢任何和所有的帮助,我很乐意回答任何人的任何问题。非常感谢。
答案 0 :(得分:2)
在SQL(更准确地说,RDBS)中,我使用以下解决方案:
1)创建一个包含以下字段的表people
- id
,name
,father_id
,mother_id
。第一个是典型的主键列,father_id和mother_id引用此列但是为NULLable(允许添加新的族行)。
2)创建一个包含以下字段的表relatives
- person_id
,ancestor_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示例,以更实用的颜色显示这一点。 )