2016-12-15 52 views
0

给定一个节点表(它们的Id及其父节点),如何获得所有根节点,内节点和叶节点?从表中获取根,内部和叶节点?

这是我到目前为止有:

根节点

SELECT Id, "Root" FROM NodeTable 
WHERE ParentId IS NULL; 

内部节点

??? 

叶节点

SELECT N1.Id, "Leaf" FROM NodeTable N1 
LEFT JOIN NodeTable N2 ON N1.Id = N2.ParentId 
WHERE N2.ParentId IS NULL; 

这是正确的吗?有一种方法可以在一个查询中做到这一点吗?

回答

3

您的“内节点”查询可以派生类似于您的“叶节点”查询。

SELECT DISTINCT N1.Id, "Inner" 
FROM NodeTable N1 
JOIN NodeTable N2 
    ON N2.ParentId = N1.ID 
WHERE N1.ParentId IS NOT NULL; 

这将让你所有这一切都没有根节点(因为他们有一个非空的ParentId)和节点(N1)的有孩子(N2)。

是的,你可以通过使用UNION关键字在一个查询中完成所有这一切。

SELECT Id, "Root" 
FROM NodeTable 
WHERE ParentId IS NULL 
UNION 
SELECT DISTINCT N1.Id, "Inner" 
FROM NodeTable N1 
JOIN NodeTable N2 
    ON N2.ParentId = N1.ID 
WHERE N1.ParentId IS NOT NULL 
UNION 
SELECT N1.Id, "Leaf" 
FROM NodeTable N1 
LEFT JOIN NodeTable N2 
    ON N1.Id = N2.ParentId 
WHERE N2.ParentId IS NULL; 
+0

真棒,太感谢你了!出于某种原因,当我自己运行内部查询时,每个节点都会出现两次。我对MySQL相当陌生,你能帮我理解为什么这样,我该如何解决它? –

+0

其实,当我使用Union关键字时,问题就消失了。奇怪的! –

+1

@IanMobbs Union是一个集合运算符。因此,如果一行被查询两次,然后与某事联合,那么该行只会显示一次。 – nasukkin

2
select case 
     when p is null then concat(n, ' Root') 
     when n in (select distinct p from bst) then concat(n, ' Inner') 
     else concat(n, ' Leaf') 
    end 
from bst 
order by n asc 
+2

你可能想详细解释这个答案。指出原始代码的错误以及如何更改它。这将使它对未来的访问者更有用。 – miken32