11

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

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)并返回一个包含所有树记录的结果集。有人可以帮我吗?

4

5 回答 5

3

好问题。在 Oracle 中,您会使用类似CONNECT BY的东西。

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

于 2010-04-07T18:13:19.200 回答
1

MySQL 不支持表值函数18.2.1。存储例程语法(这是您能够返回任意结果集所需要的)。

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

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

第三个选项具有非常小的行,将提供良好的性能并避免人为限制。

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

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

于 2012-04-14T16:30:09.093 回答
1

有一个类似的讨论可能有助于解决这个问题。

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

于 2010-04-07T18:20:37.920 回答
1

在“检索单一路径”下查看此处。但是最好使用嵌套集方法,使用树会更容易。我还建议阅读“数据库中的树 - 高级数据结构”演示文稿。

于 2010-04-11T09:48:03.050 回答
1

还需要考虑具体的路径。非常简单的概念,实际上与数据库无关。与嵌套集相比,管理插入等要容易得多,您不必在插入之前知道自己是左/右节点等。

于 2010-04-12T23:58:54.820 回答