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

发布于 2024-08-28 17:45:33 字数 413 浏览 3 评论 0原文

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

I have a MySQL table that represents data for a tree GUI component, here's the structure of my table:

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

parentId is a self-referencing foreign key.

Now I want to write a stored procedure which gets a node id and returns a result set that contains that node and all of its parents.

For example, suppose that my table has filled with this data:

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

Now I want to get all parent nodes of node 3 (nodes 1 and 2) and return a result set that contains all tree records. Can anybody help me please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

玩世 2024-09-04 17:45:34

好问题。在 Oracle 中,您可以使用诸如 CONNECT BY 之类的东西。

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

Good question. In Oracle you would use something like CONNECT BY.

Since you are using MySQL, I would suggest you change your data structure to efficiently answer that query. Here are some ideas.

葬花如无物 2024-09-04 17:45:34

有一个类似的对此进行讨论可能有助于解决此问题。

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

There was a similar discussion to this that might be helpful in solving this problem.

I think I might attack this problem by recursively retrieving the data until I'd reached the root node (parent was null). I might have been inclined to do this outside of the stored procedure initially (repeatedly calling the thing until the retrieved row had the null parent), but the "closure table" solution on the page I referenced here looks like a great solution.

三人与歌 2024-09-04 17:45:34

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

Look here under "Retrieving a Single Path". But better use a nested set approach, it will be much easier to work with a tree. Also I recommend reading "Trees In The Database - Advanced data structures" presentation.

懵少女 2024-09-04 17:45:34

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

There's also materialized paths to think about. Pretty simple concept that's really database agnostic. Much easier to manage inserts etc as in contrast to nested sets, you don't have to know you're left/right nodes etc before you insert.

恋竹姑娘 2024-09-04 17:45:34

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

如果没有它们,您将有三种选择:

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

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

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

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

MySQL does not support table valued functions 18.2.1. Stored Routine Syntax (which is what you need to be able to return an arbitrary result set).

Without them you have three choices:

  1. unroll the tree query to a fixed maximum depth and limit the permitted nesting in your hierarchy,
  2. use a loop to write the data into a temporary table and introduce some convention to return the results to the caller. You will need to consider re-entrancy, or,
  3. pre-calculate the results by including all ancestors of each component into a support table (as shown) and maintain it with triggers on the treeTable. This way, the stored procedure returns the rows in parentTable filtered appropriately. You will need to create a compound primary key and possibly indices for efficient access.

The third option has very small rows, will give good performance and avoids artificial limitations.

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

The suggestion to use a nested set approach may be appropriate in this application where the data is largely static. A rapidly changing dataset would start to impact on I/O performance as on average half of the rows in the table are updated for each insert or delete.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文