首先,大家可以先试着做这道练习题☞
题目:
给定一个表 T,id 是树节点的编号, pid 是它父节点的 id 。
树中每个节点属于以下三种类型之一:
叶子:如果这个节点没有任何孩子节点。
根:如果这个节点是整棵树的根,即没有父节点。
内部节点:如果这个节点既不是叶子节点也不是根节点。
写一个查询语句,输出所有节点的编号和节点的类型,并将结果按照节点编号排序。上面样例的结果为:
一开始我的查询语句是这样写的☞
select ID,CASE WHEN PID IS NULL THEN 'Root'
when ID not in (SELECT PID FROM T ) THEN 'Leaf'
else 'Inner' end as Type
from T
查询结果如下,明显是错误的
当我分解语句时发现,当not in() 里面包含null值,查询不会返回任何值。
所以这题正确的查询语句应该是☞
--建表
if object_id('T','U') is not null drop table T
CREATE TABLE T(ID INT,PID INT);
INSERT INTO T VALUES (1,null);
INSERT INTO T VALUES (2,1);
INSERT INTO T VALUES (3,1);
INSERT INTO T VALUES (4,2);
INSERT INTO T VALUES (5,2);
--查询
select ID,CASE WHEN PID IS NULL THEN 'Root'
when ID not in (SELECT PID FROM T WHERE PID IS NOT NULL) THEN 'Leaf'
else 'Inner' end as Type
from T
案例分析:
一、not in (包含NULL值)
select * from T where ID not in (SELECT PID FROM T )
二、not in () 查询列包含NULL 值
select * from T where PID not in (1)
查询结果: 查询不到NULL值
三、in (包含NULL值)
select * from T where PID in (NULL,1)
总结:
in 匹配的时候用的是 =
not in 匹配的时候用的是 <>
NULL 只能用 is null 或者 is not null 来判定
那么
select * from T where PID in (NULL,1)
这句查询语句相当于
select * from T where PID = NULL or PID = 1 --注意这里是OR关联条件
PID = NULL 返回是False,因为关联条件用的是or,这个条件会被忽略
select * from T where PID not in (NULL,1)
这句查询语句相当于
select * from T where PID <> NULL AND PID <> 1 --注意这里用的是and联接条件
PID = NULL 返回是False,因为关联条件用的是and,所以语句匹配不到任何值