问题描述
我有一张表,其中n是节点,p是节点的父节点。我需要找到哪个是父代,内部和叶。如果P在NULL中,则Parent是所有父项。内在是至少一叶的父母,而叶什么也没有。
n | p |
+------+------+
| 1 | 2 |
| 3 | 2 |
| 6 | 8 |
| 9 | 8 |
| 2 | 5 |
| 8 | 5 |
| 5 | NULL |
+------+------+
该表已在上面列出。我不了解此查询的工作原理。
SELECT N,IF(P IS NULL,'Root',IF((SELECT COUNT(*) FROM BST WHERE P=B.N)>0,'Inner','Leaf')) FROM BST AS B ORDER BY N;
我无法理解的部分是P = B.N。当我单独执行此查询时,它显示为零,但是当我执行此整个查询时,答案是正确的。请有人可以举例说明该查询如何与上表中的值一起使用。预先感谢
此查询的答案是
N | asnwer |
+------+--------+
| 1 | Leaf |
| 2 | Inner |
| 3 | Leaf |
| 5 | Root |
| 6 | Leaf |
| 8 | Inner |
| 9 | Leaf |
+------+--------+
在上面的查询P = BN中,没有值,例如,P的第一个值为2,N的第一个值为1。两者都不相等,并且在整个表中P的值都不等于N然后结果集如何正确。请解释
解决方法
相对于功能CASE
,我更喜欢IF()
表达式:
SELECT N,CASE
WHEN P IS NULL THEN 'Root'
ELSE CASE
WHEN (SELECT COUNT(*) FROM BST AS BB WHERE BB.P = B.N) = 0 THEN 'Leaf'
ELSE 'Inner'
END
END
FROM BST AS B
ORDER BY N;
我将条件更改为首先检查=
而不是>
。
我还对相关子查询中的表使用了别名BB
,只是想知道这不是原始查询表,而是该表的另一个 copy 。
>
对于表的每一行,检查列P
是否为null
。
如果是null
,那么结果当然是'Root'
。
如果不是null
,则必须检查的是表中列N
的值所在的行数(这是B.N
所代表的)等于列P
(这就是BB.P
所代表的含义)。
为了获得此结果,需要在表中进行计数的另一个副本。
如果结果等于0
,则意味着表中没有任何行具有N
(B.N
)作为父行,因此结果为'Leaf'
。 br />
在任何其他情况下,结果均为'Inner'
我会在case
中使用exists
表达式:
select b.*,(case when b.p is null then 'parent'
when exists (select 1 from bst b2 where b2.p = b.n) then 'inner'
else 'leaf'
end) as node_type
from bst b;
exists
只是在检查是否存在另一个父节点为该节点的节点。 where
子句是一个关联子句。您会注意到,在此版本中, all 列都使用表别名限定,因此,很清楚哪些列引用了哪些表。
在这种情况下,exists
比count()
更有效率,因为exists
可以停在第一个匹配值。