我有一个树形层次结构,它将内置于一个表中,其中parent_id指向前一个根节点。
我正在遍历所有根节点(root1,root2),我正在为root1和child1设置root1或root1 / child1的路径。为了找到child1的路径,我将至少进行2次调用以形成路径。是否有一种有效的方法来填充路径,因为我们处理了大量的根节点和子节点,这些节点和子节点的深度为5-7级。
create table foo (id, name, parent_id, path)
insert into foo (1, "root1', null, null)
insert into foo (2, "child1', 1, null)
root1 (path = null)
child1 (path = root1)
subchild1 (path = root1/child1)
root2
child2
subchild2
答案 0 :(得分:11)
您可以使用您在问题中提到的存储过程,因为嵌套可以达到7级深度。
CREATE PROCEDURE updatePath()
BEGIN
declare cnt, n int;
select count(*) into n from foo where parent_id is null;
update foo a, foo b set a.path = b.name where b.parent_id is null and a.parent_id = b.id;
select count(*) into cnt from foo where path is null;
while cnt > n do
update foo a, foo b set a.path = concat(b.path, '/', b.name) where b.path is not null and a.parent_id = b.id;
select count(*) into cnt from foo where path is null;
end while;
END//
为了检查实际记录,我们刚刚在路径列
中打印了具有空值的普通记录select * from foo
<强>结果:
| ID | NAME | PARENT_ID | PATH |
------------------------------------------
| 1 | root1 | (null) | (null) |
| 2 | child1 | 1 | (null) |
| 3 | subchild1 | 2 | (null) |
| 4 | child2 | 1 | (null) |
| 5 | child3 | 1 | (null) |
| 6 | subchild2 | 4 | (null) |
| 7 | subsubchild1 | 6 | (null) |
调用程序:
call updatepath
程序执行后的结果:
select * from foo
<强>结果:
| ID | NAME | PARENT_ID | PATH |
----------------------------------------------------------
| 1 | root1 | (null) | (null) |
| 2 | child1 | 1 | root1 |
| 3 | subchild1 | 2 | root1/child1 |
| 4 | child2 | 1 | root1 |
| 5 | child3 | 1 | root1 |
| 6 | subchild2 | 4 | root1/child2 |
| 7 | subsubchild1 | 6 | root1/child2/subchild2 |
希望这会有所帮助......
答案 1 :(得分:1)
我非常喜欢Modified Preorder Tree Traversal。它允许您在单个查询中获得整个树层次结构。这是一个详细的教程:http://www.sitepoint.com/hierarchical-data-database-2/
如果您对MPTT有任何疑问,请告诉我,我很乐意提供帮助!
答案 2 :(得分:0)
虽然在单个调用中不是严格可行的,但您可以隐藏多个调用,但将它们放入您从SQL调用的MySQL函数中,该函数将返回父路径。
虽然这可能比在脚本中执行它更有效,但我不希望它有效。
如果最大级别数被修复,您可以按如下方式使用JOIN: -
SELECT foo.id, foo.name, CONCAT_WS(',', d.name, c.name, b.name, a.name)
FROM foo
LEFT OUTER JOIN foo a ON foo.parent_id = a.id
LEFT OUTER JOIN foo b ON a.parent_id = b.id
LEFT OUTER JOIN foo c ON b.parent_id = c.id
LEFT OUTER JOIN foo d ON c.parent_id = d.id
虽然这会起作用,但它是非常有限的(即,如果最大级别更改,则必须使用此更改SQL的每一位),再加上如果级别的数量不是很小,它将变得不可读混乱。
答案 3 :(得分:0)
您可以考虑将包含每个树根的所有closure table的paths添加到树叶中。 Maintaining the transitive closure of graphs in SQL(自1999年起)描述了一些理论背景。
Hierarchical data上的stackoverflow review question描述了许多替代方法。在那里,Tegiri Nenashi指向包含Hierarchical data in RDBMSs的综合参考书目。
Closure表的优势在于查询是高效的,并且解决方案不会影响您当前的数据结构。您需要使用闭包表进行扩展,并在修改林时对其进行维护。
表示表中包含短路径的大量项目。这使得闭包表的性能与适当的指数保持近似线性。您还可以保留关闭表中每个节点的路径,以避免重新计算。该方法对每个操作都有一定数量的查询,并支持任何深度的层次结构。
答案 4 :(得分:0)