开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
描述
给定表 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 |
+------+
解析
这是一道数据库题目,本来不想记录这道题的,因为大家可能都会觉得太简单了,我第一眼也是这么认为,没想到有个小细节被忽略了,我第一眼看过去直接就想着答案就是:
SELECT name FROM customer WHERE referee_Id <> 2;
仔细想一下或者尝试一下结果,其实这是一个错的答案,这个查询结果只会返回一个Zach,这里大家就会想起来,这六条数据中有三条是NULL值,而对于NULL值的比较,就涉及到一个知识点。
在MySQL中的比较结果有三种,分别是TRUE、FALSE和UNKNOWN,在查询语句中,使用where或者having时,只有结果是true的时候才会被输出,false和unknown都不会被输出。
那什么时候会出现unknown的结果呢,当空值NULL与另一个值,这个值可以是NULL进行比较时,他们的运算结果为unknown,也就是我们上面的这个referee_Id <> 2条件,当referee_Id为NULL时,比较结果是unknown,是不会被返回的。
此外,空值NULL进行算术运算的结果也是NULL,如:NULL+1的结果是NULL。
因此,正确的写法有以下两种:
-- 方式一
SELECT name FROM customer WHERE referee_id != 2 OR referee_id IS NULL;
-- 方式二
SELECT name FROM customer WHERE referee_id != 2
union all
SELECT name FROM customer WHERE referee_id IS NULL;
这里更推荐 方式二,因为使用or会导致索引失效的情况,但是使用union的时候要注意一点,如果是union all的话是不会去重的,比如结果集中有两个name是Will的,那都会被查出来,单独使用union的话,会进行去重,也就是结果集只会有一条Will的返回值。
运行结果:
执行结果:通过
执行用时:491 ms, 在所有 MySQL 提交中击败了71.39%的用户
内存消耗:0 B, 在所有 MySQL 提交中击败了100.00%的用户