如何在分层mysql表中选择节点的所有父节点?

时间:2010-04-07 18:07:21

标签: mysql tree hierarchical

我有一个表示树GUI组件数据的MySQL表,这是我表的结构:

treeTable ( 
  id INT NOT NULL PRIMARY KEY, 
  parentId INT, 
  name VARCHAR(255) 
);

parentId是一个自引用外键。

现在我想编写一个存储过程,它获取一个节点id并返回一个包含该节点及其所有父节点的结果集。

例如,假设我的表填充了这些数据:

1, null, 'root'
2, 1   , 'level_1'
3, 2   , 'level_2'

现在我想获取节点3(节点1和2)的所有父节点,并返回包含所有树记录的结果集。请有人帮帮我吗?

5 个答案:

答案 0 :(得分:3)

好问题。在Oracle中,您可以使用 CONNECT BY

由于您使用的是MySQL,我建议您更改数据结构以有效地回答该查询。 Here是一些想法。

答案 1 :(得分:1)

There was a similar discussion对此可能有助于解决此问题。

我想我可能会通过递归检索数据来解决这个问题,直到我到达根节点(parent为null)。我可能最初倾向于在存储过程之外执行此操作(重复调用该事物直到检索到的行具有null父项),但是我在此处引用的页面上的“闭包表”解决方案看起来是一个很好的解决方案。

答案 2 :(得分:1)

在“检索单一路径”下查看here。但最好使用嵌套集方法,使用树更容易。另外,我建议阅读“Trees In The Database - Advanced data structures”演示文稿。

答案 3 :(得分:1)

还有materialized paths要考虑的问题。非常简单的概念,它真的与数据库无关。与嵌套集相比,管理插入等更容易,在插入之前,您不必知道左/右节点等。

答案 4 :(得分:1)

MySQL不支持表值函数18.2.1. Stored Routine Syntax(这是您需要能够返回任意结果集的函数)。

没有它们,你有三个选择:

  1. 将树查询展开到固定的最大深度,并限制层次结构中允许的嵌套,
  2. 使用循环将数据写入临时表,并引入一些约定以将结果返回给调用者。您需要考虑重新入侵,或
  3. 通过将每个组件的所有祖先包含在支持表(如图所示)中并使用treeTable上的触发器维护它来预先计算结果。这样,存储过程返回parentTable中适当过滤的行。您需要创建一个复合主键和可能的索引以便有效访问。
  4. 第三种选择具有非常小的行,将提供良好的性能并避免人为限制。

    parentTable (
        id INT NOT NULL,
        parentId INT NOT NULL
    ); 
    

    在数据基本上是静态的应用程序中,使用嵌套集方法的建议可能是合适的。快速变化的数据集将开始影响I / O性能,因为每次插入或删除时,表中的平均一半行都会更新。