LeetCode Tree Node问题:我的T-SQL查询为何出错?
LeetCode Tree Node问题排查
问题场景
现有Tree表包含id和p_id两列,需要将每个节点id分为三类:
- Root:
p_id为null的节点 - Inner:有父节点(
p_id不为null)且存在子节点(自身id出现在p_id列中) - Leaf:自身id未出现在
p_id列中的节点
你用UNION分三部分查询的代码在Leaf节点查询时失效,单独测试Leaf节点的子查询返回空,移除and id not in (select distinct(p_id) from tree)条件后能正确返回Inner和Leaf节点,问题就出在这个NOT IN条件上。
失效原因
核心问题是NOT IN子查询包含NULL值。当select distinct(p_id) from tree的结果里存在NULL(比如Root节点的p_id就是NULL),此时id NOT IN (..., NULL)的逻辑会直接失效:
SQL中任何值和NULL做比较都会返回UNKNOWN,而NOT IN要求所有子查询结果都不等于当前id,只要有一个比较结果是UNKNOWN,整个NOT IN条件就会判定为不成立,最终过滤掉所有行,导致Leaf节点查询返回空。
修正方案
方案1:子查询排除NULL值
修改Leaf节点的过滤条件,在子查询里先排除p_id为NULL的情况:
select id, 'Leaf' from tree where p_id is not null and id not in (select distinct p_id from tree where p_id is not null)
方案2:改用NOT EXISTS(更推荐)
NOT EXISTS对NULL的处理更友好,不会出现上述逻辑问题:
select id, 'Leaf' from tree t1 where p_id is not null and not exists (select 1 from tree t2 where t2.p_id = t1.id)
方案3:用CASE WHEN简化整个查询(更简洁高效)
可以不用UNION拆分查询,直接用CASE WHEN一次性完成分类,避免多段查询的潜在问题:
select id, case when p_id is null then 'Root' when exists (select 1 from tree t where t.p_id = tree.id) then 'Inner' else 'Leaf' end as type from tree
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

