请问这个查询可以解释一下吗?
Can this query explained please?
我有一个 table,其中 n 是节点,p 是节点的父节点。我需要找到哪个是父级、内部和叶子。 Parent 是所有 if P in NULL 的父级。 inner是至少一个叶子的父元素,叶子什么都没有。
n | p |
+------+------+
| 1 | 2 |
| 3 | 2 |
| 6 | 8 |
| 9 | 8 |
| 2 | 5 |
| 8 | 5 |
| 5 | NULL |
+------+------+
上面列出了table。我不明白这个查询是如何工作的。
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。当我单独执行此查询时,它显示计数为零,但当我执行整个查询时,答案是正确的。请有人举例说明此查询如何使用从上述 table 中获取的值。提前致谢
此查询的答案是
N | asnwer |
+------+--------+
| 1 | Leaf |
| 2 | Inner |
| 3 | Leaf |
| 5 | Root |
| 6 | Leaf |
| 8 | Inner |
| 9 | Leaf |
+------+--------+
在上面的查询中 P=B.N 没有值,例如,P 的第一个值是 2,N 的第一个值是 1。两者不相等并且在整个 table 没有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;
我将先检查的条件更改为 =
而不是 >
。
我还在相关子查询中为 table 使用别名 BB
只是为了让我知道这不是原始查询的 table 而是另一个 copy 的 table.
对于 table 的每一行,检查列 P
是否为 null
。
如果是null
那么结果当然是'Root'
.
如果不是 null
那么必须检查的是 table 中的行数,其中 table 的列 N
的值(这就是 B.N
代表的内容)等于列 P
(这就是 BB.P
代表的内容)。
为了获得此结果,需要对 table 进行计数的另一个 副本。
如果结果等于 0
,这意味着 table 中没有任何行以 N
(B.N
) 作为父级,因此结果为 'Leaf'
.
在任何其他情况下,结果是 '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
子句是一个关联子句。您会注意到,在此版本中,所有 列都使用 table 别名进行限定,因此很清楚哪些列指的是哪些 table。
在这种情况下,exists
比 count()
更有效,因为 exists
可以在第一个匹配值处停止。
我有一个 table,其中 n 是节点,p 是节点的父节点。我需要找到哪个是父级、内部和叶子。 Parent 是所有 if P in NULL 的父级。 inner是至少一个叶子的父元素,叶子什么都没有。
n | p |
+------+------+
| 1 | 2 |
| 3 | 2 |
| 6 | 8 |
| 9 | 8 |
| 2 | 5 |
| 8 | 5 |
| 5 | NULL |
+------+------+
上面列出了table。我不明白这个查询是如何工作的。
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。当我单独执行此查询时,它显示计数为零,但当我执行整个查询时,答案是正确的。请有人举例说明此查询如何使用从上述 table 中获取的值。提前致谢
此查询的答案是
N | asnwer |
+------+--------+
| 1 | Leaf |
| 2 | Inner |
| 3 | Leaf |
| 5 | Root |
| 6 | Leaf |
| 8 | Inner |
| 9 | Leaf |
+------+--------+
在上面的查询中 P=B.N 没有值,例如,P 的第一个值是 2,N 的第一个值是 1。两者不相等并且在整个 table 没有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;
我将先检查的条件更改为 =
而不是 >
。
我还在相关子查询中为 table 使用别名 BB
只是为了让我知道这不是原始查询的 table 而是另一个 copy 的 table.
对于 table 的每一行,检查列 P
是否为 null
。
如果是null
那么结果当然是'Root'
.
如果不是 null
那么必须检查的是 table 中的行数,其中 table 的列 N
的值(这就是 B.N
代表的内容)等于列 P
(这就是 BB.P
代表的内容)。
为了获得此结果,需要对 table 进行计数的另一个 副本。
如果结果等于 0
,这意味着 table 中没有任何行以 N
(B.N
) 作为父级,因此结果为 'Leaf'
.
在任何其他情况下,结果是 '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
子句是一个关联子句。您会注意到,在此版本中,所有 列都使用 table 别名进行限定,因此很清楚哪些列指的是哪些 table。
在这种情况下,exists
比 count()
更有效,因为 exists
可以在第一个匹配值处停止。