【SQL】leetcode 584.寻找用户推荐人(知识点:SQL的三值逻辑)

本文介绍了如何在MySQL中处理三值逻辑,特别是针对NULL的情况。通过一道LeetCode题目584,解释了为什么在查询时不能简单地使用!=2来过滤掉推荐人编号为2的客户,原因是NULL的处理方式。文章强调了NULL的含义和在查询中的行为,以及正确使用IS NOT NULL或IS DISTINCT FROM来解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

给定表 customer ,里面保存了所有客户信息和他们的推荐人。

+------+------+-----------+
| id   | name | referee_id|
+------+------+-----------+
|    1 | Will |      NULL |
|    2 | Jane |      NULL |
|    3 | Alex |         2 |
|    4 | Bill |      NULL |
|    5 | Zack |         1 |
|    6 | Mark |         2 |
+------+------+-----------+

写一个查询语句,返回一个客户列表,列表中客户的推荐人的编号都 不是 2。

结果示例

对于上面的示例数据,结果为:

+------+
| name |
+------+
| Will |
| Jane |
| Bill |
| Zack |
+------+


解答思路

一开始拿到这个题的做法是:

# Write your MySQL query statement below
SELECT name
FROM customer
WHERE referee_id <> 2;

但是结果报错,发现所有referee_idNULL的数据都被忽略了。同样,使用过滤条件 WHERE referee_id <> 2 OR referee_id = NULL也是错的,为什么?
查了一些解答,总结一下:

首先,来了解一下 MySQL背后的三值逻辑:TRUEFALSEUNKOWN
TRUEFALSE很好理解,真和假。
对于UNKOWNNULL,也有一个非常通俗的解释(来源于文末参考链接中的橡树😎):

UNKOWN是说,“未知”。当人们戴上墨镜之后,人们不知道墨镜底下的眼珠是什么颜色,这就是未知,即“unknown”。虽然不知道,但是人的眼珠不管是红色、黑色还是棕色,肯定是有颜色的。

放在数据表中同理,我们拿到Jane的推荐人id,发现是NULL,不是因为推荐人没有id,而是因为我们不知道这个对应的推荐人id是什么而已。
同样,对于NULL,还有另外一种解释:

inapplicable,不适用。比如一个属性,生理性别,对于人来说,这个属性有意义,每个人都有对应的生理性别属性:男/女。但是对于物品,比如电脑、冰箱来说,是没有这个属性的。因此也被称为“不适用”。

现有的DBMS将两种类型的NULL归为一类,并采用了上面提到的三值逻辑。
那么查询结果中为什么不会包含含有在这里插入代码片NULL的行呢?这是因为查询结果中只会包含 WHERE子句中判断结果为TRUE的行FALSEUNKNOWN不在考虑范围内。因此 我们如果要查推荐人的编号不是2,不应该使用referee_id != 2referee_id <> 2)这样的条件,这会导致UNKOWN的情况被忽略了。

那么可不可以使用 referee_id = NULL呢?答案也是否定的。
为什么?
划重点!!!因为NULL不是值,类似于汉语的说话习惯,MySQL中也有所谓的谓词,比如(=,>,<>等等用来判断值的保留字),但是由于NULL本身不属于值得一种,因此对其使用谓词,返回得结果必然不可能是TRUE,而是UNKNOWN。

那这道题应该用什么呢?答案是IS NULLIS NOT NULL。首先,IS NULL不是ISNULL。而仅仅是对某个字符是否为空的一种判断,再想象一下一个例子:在某个表中,一个人的性别不知道,显示为NULL,我们在描述这个情况时,可以认为数据遗漏,这个人的性别信息是未知的,但是我们不能直接使用一些谓词,比如=,<,>,!=对性别信息是未知的这一现象进行判断。

小结

当原数据中含有NULL时,最好用IS NULL或IS NOT NULL作为WHERE的补充过滤条件。

正确代码

# Write your MySQL query statement below
SELECT name
FROM customer
WHERE referee_id <> 2 OR referee_id IS NULL;

参考资料:
[1] https://leetcode-cn.com/problems/find-customer-referee/solution/san-by-xiang-shu-k-7ywp/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值