这是您要求的查询:
# By using LEFT JOINs you will be able to read any record,
# even one with missing parent/grand-parent...
SELECT
child.id,
child.name,
parent.id,
parent.name,
gparent.id,
gparent.name
FROM
some_table child
LEFT JOIN some_table parent ON
parent.id = child.parent_id
LEFT JOIN some_table gparent ON
gparent.id = child.grandparent_id
WHERE
child.id = 3
但我还要补充一点,拥有一个字段 grandparent_id 的冗余对我来说并不正确......
你的桌子应该是:
id name parent_id
1 Milton NULL
2 Year 3 1
3 Class A 2
请注意,如果我知道 1 是 2 的父级,我不需要在记录中再次重复相同的信息 3...
在最后一种情况下,您的选择可能是这样的:
SELECT
child.id,
child.name,
parent.id,
parent.name,
gparent.id,
gparent.name
FROM
some_table child
LEFT JOIN some_table parent ON
parent.id = child.parent_id
LEFT JOIN some_table gparent ON
gparent.id = parent.parent_id -- See the difference?
WHERE
child.id = 3
查询的工作方式相同,您还将拥有更多“规范化”的数据库。
编辑:这是非常基本的东西,但我想它与这个答案有关......
不应使用这种非规范化(即在同一记录上同时具有 parent_id 和 grandparent_id),因为它允许数据库不一致。
例如,假设插入了一条新记录:
id name parent_id grandparent_id
1 Milton NULL NULL
2 Year 3 1 NULL
3 Class A 2 1
4 Invalid Rec 2 3
这没有任何意义,对吧?记录 4 声明 3 是它的祖父母。因此,3 应该是记录 2 的父项。但这不是3 本身记录的内容。哪个记录是正确的?
您可能认为这是一个奇怪的错误,并且您的数据库永远不会变成这样。但我的经验并非如此——如果可能发生错误,它最终会发生。应该避免非规范化,不仅仅是因为某些数据库专家这么说,而是因为它确实增加了不一致性,并使维护变得更加困难。
当然,非规范化数据库可能会更快。但是,根据经验,您应该在您的系统准备好投入生产之后考虑性能,并且在您通过一些自动化或经验测试的方式感知到之后,即存在瓶颈。相信我,我之前看到过更糟糕的设计选择被错误的性能预期证明是合理的......