如何找到层次树中的所有子节点
how to find all the child nodes in hierarchical tree
我有一个 table 由 fk parentId 自引用。
给定一个id,我需要提取它的所有子节点。
我知道该图正好具有三个级别:root、middleNode、leaf
所以我尝试了这个:
SELECT *
FROM table AS root
LEFT JOIN table AS middle
ON middle.parentId = root.id
LEFT JOIN table AS leaf
ON leaf.parentId = middle.id
WHERE root.id = 1
但是这样我就没有每个节点的行...
此外,此实现没有考虑两件事:
- 链接到3层结构
- 在我看来,如果我在树的中间搜索,这似乎不是最好的解决方案
3个级别,你可以用
SELECT * FROM
-- root
(
SELECT *
FROM your_table WHERE id = 1
) as root
UNION ALL
-- level1
(
SELECT * FROM your_table WHERE parentId = 1 )
)
UNION ALL
-- level2
(
SELECT * FROM your_table WHERE parentId IN (SELECT id FROM your_table WHERE parentId = 1 )
)
但是对于更深的深度,我建议你实现常见的方法,例如嵌套集模型(需要添加额外的列),请take a look on this
如果你想从你所在的点向下走,你可以使用临时 table。
CREATE TABLE tempTable (id int, parentid int);
INSERT INTO tempTable (id, parentid)
SELECT id, parentID FROM tree WHERE id = @input;
SET @LastCount=0;
SELECT @Count = COUNT(1) FROM tempTable;
WHILE @LastCount != @Count DO
INSERT INTO tempTable (id, parentid)
SELECT id,parentid from tree where id in (SELECT parentid FROM TempTable) AND ID NOT IN (SELECT id FROM TempTable);
@LastCount = @Count;
SELECT @Count = COUNT(1) FROM tempTable;
END WHILE;
SELECT * FROM tempTable;
DROP tempTable;
这将一遍又一遍地循环,在层次结构中进一步向下,添加当前在 table 中具有父级的行,只要这些行还不存在,并在添加时结束循环没有新行(最后一个循环行数 = 当前循环行数)这样做的好处是根本不关心层次结构的大小,它可以是 3 级或 30 级,也不关心你从哪里开始,它总是再降一级。
如果您想要包含该节点的整个层次结构,您可以沿着层次结构向上循环,直到找到没有父节点的节点(如果您在同一 table 中有多个树,比如多个仓库过道、货架、各仓库顶层):
SET @next = @input;
WHILE @next IS NOT NULL DO
SET @topID = @next;
SELECT @next = parentID FROM tree WHERE id=@topID;
END WHILE
CREATE TABLE tempTable (id int, parentid int);
INSERT INTO tempTable (id, parentid);
SELECT id, parentID FROM table WHERE id = @topID;
SET @LastCount=0;
SELECT @Count = COUNT(1) FROM tempTable;
WHILE @LastCount != @Count DO
INSERT INTO tempTable (id, parentid)
SELECT id,parentid from tree where id in (SELECT parentid FROM TempTable) AND ID NOT IN (SELECT id FROM TempTable);
@LastCount = @Count;
SELECT @Count = COUNT(1) FROM tempTable;
END WHILE;
SELECT * FROM tempTable;
DROP tempTable;
这将 运行 到达树的顶部,然后逐层向下循环。任何一个都可以在 while 循环中使用计数器变量来找到从你开始的点开始的相对水平。
SQLFiddle 不允许其中一些函数在 MySQL 上正常工作,但我有一个 MsSQL fiddle 显示此函数有效 - MsSql Fiddle
我有一个 table 由 fk parentId 自引用。
给定一个id,我需要提取它的所有子节点。
我知道该图正好具有三个级别:root、middleNode、leaf
所以我尝试了这个:
SELECT *
FROM table AS root
LEFT JOIN table AS middle
ON middle.parentId = root.id
LEFT JOIN table AS leaf
ON leaf.parentId = middle.id
WHERE root.id = 1
但是这样我就没有每个节点的行...
此外,此实现没有考虑两件事:
- 链接到3层结构
- 在我看来,如果我在树的中间搜索,这似乎不是最好的解决方案
3个级别,你可以用
SELECT * FROM
-- root
(
SELECT *
FROM your_table WHERE id = 1
) as root
UNION ALL
-- level1
(
SELECT * FROM your_table WHERE parentId = 1 )
)
UNION ALL
-- level2
(
SELECT * FROM your_table WHERE parentId IN (SELECT id FROM your_table WHERE parentId = 1 )
)
但是对于更深的深度,我建议你实现常见的方法,例如嵌套集模型(需要添加额外的列),请take a look on this
如果你想从你所在的点向下走,你可以使用临时 table。
CREATE TABLE tempTable (id int, parentid int);
INSERT INTO tempTable (id, parentid)
SELECT id, parentID FROM tree WHERE id = @input;
SET @LastCount=0;
SELECT @Count = COUNT(1) FROM tempTable;
WHILE @LastCount != @Count DO
INSERT INTO tempTable (id, parentid)
SELECT id,parentid from tree where id in (SELECT parentid FROM TempTable) AND ID NOT IN (SELECT id FROM TempTable);
@LastCount = @Count;
SELECT @Count = COUNT(1) FROM tempTable;
END WHILE;
SELECT * FROM tempTable;
DROP tempTable;
这将一遍又一遍地循环,在层次结构中进一步向下,添加当前在 table 中具有父级的行,只要这些行还不存在,并在添加时结束循环没有新行(最后一个循环行数 = 当前循环行数)这样做的好处是根本不关心层次结构的大小,它可以是 3 级或 30 级,也不关心你从哪里开始,它总是再降一级。
如果您想要包含该节点的整个层次结构,您可以沿着层次结构向上循环,直到找到没有父节点的节点(如果您在同一 table 中有多个树,比如多个仓库过道、货架、各仓库顶层):
SET @next = @input;
WHILE @next IS NOT NULL DO
SET @topID = @next;
SELECT @next = parentID FROM tree WHERE id=@topID;
END WHILE
CREATE TABLE tempTable (id int, parentid int);
INSERT INTO tempTable (id, parentid);
SELECT id, parentID FROM table WHERE id = @topID;
SET @LastCount=0;
SELECT @Count = COUNT(1) FROM tempTable;
WHILE @LastCount != @Count DO
INSERT INTO tempTable (id, parentid)
SELECT id,parentid from tree where id in (SELECT parentid FROM TempTable) AND ID NOT IN (SELECT id FROM TempTable);
@LastCount = @Count;
SELECT @Count = COUNT(1) FROM tempTable;
END WHILE;
SELECT * FROM tempTable;
DROP tempTable;
这将 运行 到达树的顶部,然后逐层向下循环。任何一个都可以在 while 循环中使用计数器变量来找到从你开始的点开始的相对水平。
SQLFiddle 不允许其中一些函数在 MySQL 上正常工作,但我有一个 MsSQL fiddle 显示此函数有效 - MsSql Fiddle