0

这是我正在使用的课程:https ://gist.github.com/2174233

我有两张表:一张表包含用户,另一张表包含闭包。

当我使用get_children()方法时(比如说从根或另一个父级),它只显示层次结构的第一级。lvl 我应该在列中存储什么值?

这是闭包表的定义,我有:

 CREATE TABLE closures (
     id         INT(11) NOT NULL AUTO_INCREMENT,
     ancestor   INT(11) NOT NULL,
     descendant INT(11) NOT NULL,
     lvl        INT(11) NOT NULL,

     PRIMARY KEY (id)
 )

这是我存储在闭包表中的数据示例:

INSERT INTO `closures` (`id`, `ancestor`, `descendant`, `lvl`) 
VALUES (1, 1, 20, 0),
       (4, 20, 26, 0),
       (5, 26, 25, 0);

最后是lvl列,但我不知道那里有什么值。你能给我一个如何使用它的建议吗?

我必须存储的结构有 3 个级别:根 -> 20 节点 -> 26 节点,但它只给了我第一级子节点,即 20 节点。

4

1 回答 1

3

我建议您阅读SQL Antipatterns书。第二章将闭包表作为实现类别树的推荐方法之一。

那就是说。看起来你的闭包表有点奇怪。那里的id列没有意义。相反,您应该有一个复合主键,由一对唯一的祖先和后代值组成。

而且您还没有插入节点本身..只有两个不同节点之间的连接。也许阅读“用闭包表渲染树”可以对这个主题有所启发。

猜测INSERT声明应该是这样的(至少是我的结论):

INSERT INTO closures(ancestor, descendant, lvl) 
VALUES (1,  1,  null),
       (20, 20, null),
       (26, 26, null),
       (28, 28, null),
       (1,  20, 1),
       (20, 26, 2),
       (26, 25, 3);

您必须了解的是,闭包表不存储树。相反,您正在使用的数据结构是有向图。像这样的东西:

在此处输入图像描述

如您所见,该图具有三个根节点:3、5 和 7。此外,非常重要的是要注意,节点 10 的深度级别不同,具体取决于您从哪个根节点开始。

它将用两个闭包定义:[3,10,1] 和 [11,10,2]。意思是,来自第 11 个节点的连接将其置于二级,而从第 3 个节点开始,它是一级项目。

问题是,当您使用闭包表时,每个类别都可以有多个父类别,每个类别的深度都不同


加法(@ypercube):

我对“级别”或“深度”列的理解是它存储了从祖先到后代的“距离”(需要走的步骤)。它不是节点的绝对级别,因此闭包表可用于存储比树图更复杂的图。你甚至可能有多个从祖先到后代的路径,每一个(路径)都有不同的步骤。

此外,Nulls 应该为 0,并且需要更多的行。

因此,数据将是:

INSERT INTO closures(ancestor, descendant, lvl) 
VALUES ( 1,  1,  0), (20, 20, 0), (26, 26, 0), (25, 25, 0),
                     ( 1, 20, 1), (20, 26, 1), (26, 25, 1),
                                  ( 1, 26, 2), (20, 25, 2),
                                               ( 1, 25, 3) ;
于 2012-07-08T03:02:39.317 回答