插入时为什么闭包表指向自身

时间:2014-03-14 22:05:11

标签: mysql sql closures

关于关闭表的Bill Karwin'教程,我从未理解为什么节点需要指向自身。举个例子:

创建表

create table closure (
    ancestor int not null,
    descendant int not null,
    primary key (ancestor, descendant),
    foreign key (ancestor) references nodes(node),
    foreign key (descendant) references nodes(node)
);

插入假设这些ID存在

insert into closure (ancestor, descendant) values
    (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7),
    (2,2),
    (3,3), (3,4), (3,5),
    (4,4), (4,5),
    (5,5),
    (6,6), (6,7),
    (7,7); // <-- junction to itself?

我真正理解的部分是为什么使用(1,1)或(2,2)或(3,3)等...。我试着谷歌搜索答案,但我似乎永远无法找到正确的关键词。

由于

2 个答案:

答案 0 :(得分:2)

树中的每个节点都需要与closure中至少有一行对应,其中idancestor。如果节点是叶子,则它没有任何真正的后代,并且通过将descendant指向自身来表示这种退化情况。

我相信他为非叶子节点创建了一个自引用行,这样就可以安全地删除带有ancestor的其他行 - 当删除所有后代时,该节点将继续存在。

答案 1 :(得分:1)

(#1)正如Barmar所提到的,自引用节点允许叶节点继续存在&#39;在闭包表中,如果它的所有祖先都被删除了。

(#2)同样,如果要移动子树,则在子树被切断时始终存在根节点&#39;来自其原始祖先。如果没有这个,我认为移动子树的过程可能会有些麻烦。

(#3)同样,自引用节点允许在闭包表中不存在没有后代的根节点。

(#4)看过Bill Karwin的一些例子,我认为它可以帮助你编写不那么复杂,效率更高的SQL查询,但我不是SQL专家足以证明这一点。

所有这一切,在提供的示例user1318677中,自引用记录占表格的41%,这对我来说是一个相当大的数量。如果您的项目没有经常发生(#1)(#2)(例如基本论坛/评论系统),那么我认为自我引用节点主要是冗余数据,并且您不一定需要它们。

如果其他人能证明不是这样,我很乐意听到它。

作为旁注,在评论部分回答用户1318677的问题:是的,可以拥有任意数量的根节点(例如,每个原始帖子的1个根节点到论坛)。