关于关闭表的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)等...。我试着谷歌搜索答案,但我似乎永远无法找到正确的关键词。
由于
答案 0 :(得分:2)
树中的每个节点都需要与closure
中至少有一行对应,其中id
是ancestor
。如果节点是叶子,则它没有任何真正的后代,并且通过将descendant
指向自身来表示这种退化情况。
我相信他为非叶子节点创建了一个自引用行,这样就可以安全地删除带有ancestor
的其他行 - 当删除所有后代时,该节点将继续存在。
答案 1 :(得分:1)
(#1)正如Barmar所提到的,自引用节点允许叶节点继续存在&#39;在闭包表中,如果它的所有祖先都被删除了。
(#2)同样,如果要移动子树,则在子树被切断时始终存在根节点&#39;来自其原始祖先。如果没有这个,我认为移动子树的过程可能会有些麻烦。
(#3)同样,自引用节点允许在闭包表中不存在没有后代的根节点。
(#4)看过Bill Karwin的一些例子,我认为它可以帮助你编写不那么复杂,效率更高的SQL查询,但我不是SQL专家足以证明这一点。
所有这一切,在提供的示例user1318677中,自引用记录占表格的41%,这对我来说是一个相当大的数量。如果您的项目没有经常发生(#1)或(#2)(例如基本论坛/评论系统),那么我认为自我引用节点主要是冗余数据,并且您不一定需要它们。
如果其他人能证明不是这样,我很乐意听到它。
作为旁注,在评论部分回答用户1318677的问题:是的,可以拥有任意数量的根节点(例如,每个原始帖子的1个根节点到论坛)。