MySQL条件查询IN和NOT IN左右两侧包含NULL值的处理方式
卡了一晚上的一个问题,基础不牢,地动山摇!
题目
给定一个表 tree,id 是树节点的编号, p_id 是它父节点的 id 。
+----+------+| id | p\_id |+----+------+| 1 | NULL || 2 | 1 || 3 | 1 || 4 | 2 || 5 | 2 |+----+------+
树中每个节点属于以下三种类型之一:
叶子:如果这个节点没有任何孩子节点。
根:如果这个节点是整棵树的根,即没有父节点。
内部节点:如果这个节点既不是叶子节点也不是根节点。
写一个查询语句,输出所有节点的编号和节点的类型,并将结果按照节点编号排序。上面样例的结果为:
+----+------+| id | TYPE |+----+------+| 1 | Root || 2 | INNER|| 3 | Leaf || 4 | Leaf || 5 | Leaf |+----+------+
解释
节点 ‘1’ 是根节点,因为它的父节点是 NULL ,同时它有孩子节点 ‘2’ 和 ‘3’ 。
节点 ‘2’ 是内部节点,因为它有父节点 ‘1’ ,也有孩子节点 ‘4’ 和 ‘5’ 。
节点 ‘3’, ‘4’ 和 ‘5’ 都是叶子节点,因为它们都有父节点同时没有孩子节点。
样例中树的形态如下:
1/ \\2 3/ \\4 5
首先先建表
1.建表
CREATE TABLE tree(
id INT ,
p_id INT
)
下面是我的做法:
SELECT id,(
CASE WHEN tree.p_id IS NULL THEN 'Root'WHEN tree.id NOT IN ( -- id不在父结点p_id列时,认为是叶子结点,逻辑上没有问题!SELECT p_idFROM treeGROUP BY p_id) THEN 'Leaf'ELSE 'Inner'
END
)TYPE
FROM tree
我觉得当id不在父结点p_id列时,认为是叶子结点,这在逻辑上完全没有任何问题,然而事情并没有这么简单,查询结果如下:从id=3开始没有查到我想要的结果!神奇吧!
于是又过了一晚上,终于解决了问题,我先给出正确的做法:
SELECT id,(
CASE WHEN tree.p_id IS NULL THEN 'Root'WHEN tree.id NOT IN (SELECT p_idFROM treeWHERE p_id IS NOT NULL -- 添加了一句SQLGROUP BY p_id) THEN 'Leaf'ELSE 'Inner'
END
)TYPE
FROM tree
为什么会这样呢?
我们都知道
MySQL 中的 IN 运算符用来判断表达式的值是否位于给出的列表中;如果是,返回值为 1,否则返回值为 0。NOT IN 的作用和 IN 恰好相反,NOT IN 用来判断表达式的值是否不存在于给出的列表中;如果不是,返回值为 1,否则返回值为 0。
一般情况下我们都是这样用的,结果也是我们想要的。但是下面的特殊情况我们却经常遇到!
(1)in和not in左右两侧都没有NULL值的情况
【实例1】在 SQL 语句中使用 IN 和 NOT IN 运算符:
mysql> SELECT 2 IN (1,3,5,'thks'),'thks' IN (1,3,5, 'thks');
+---------------------+---------------------------+
| 2 IN (1,3,5,'thks') | 'thks' IN (1,3,5, 'thks') |
+---------------------+---------------------------+
| 0 | 1 |
+---------------------+---------------------------+
1 row in set, 2 warnings (0.00 sec)mysql> SELECT 2 NOT IN (1,3,5,'thks'),'thks' NOT IN (1,3,5, 'thks');
+-------------------------+-------------------------------+
| 2 NOT IN (1,3,5,'thks') | 'thks' NOT IN (1,3,5, 'thks') |
+-------------------------+-------------------------------+
| 1 | 0 |
+-------------------------+-------------------------------+
1 row in set, 2 warnings (0.00 sec)
由结果可以看到,IN 和 NOT IN 的返回值正好相反。
但是忽略了一个NULL值问题
对空值 NULL 的处理
当 IN 运算符的两侧有一个为空值 NULL 时,如果找不到匹配项,则返回值为 NULL;如果找到了匹配项,则返回值为 1。
(2)NULL值在in左右两侧
请看下面的 SQL 语句如下:
mysql> SELECT NULL IN (1,3,5,'thks'),10 IN (1,3,NULL,'thks');
+------------------------+-------------------------+
| NULL IN (1,3,5,'thks') | 10 IN (1,3,NULL,'thks') |
+------------------------+-------------------------+
| NULL | NULL |
+------------------------+-------------------------+
1 row in set, 1 warning (0.00 sec)mysql> SELECT NULL IN (1,3,5,'thks'),10 IN (1,10,NULL,'thks');
+------------------------+--------------------------+
| NULL IN (1,3,5,'thks') | 10 IN (1,10,NULL,'thks') |
+------------------------+--------------------------+
| NULL | 1 |
+------------------------+--------------------------+
1 row in set (0.00 sec)
(3)NULL在NOT IN 的其中一侧
NOT IN 恰好相反,当 NOT IN 运算符的两侧有一个为空值 NULL 时,如果找不到匹配项,则返回值为 NULL;如果找到了匹配项,则返回值为 0。
请看下面的 SQL 语句如下:
mysql> SELECT NULL NOT IN (1,3,5,'thks'),10 NOT IN (1,0,NULL,'thks');
+----------------------------+-----------------------------+
| NULL NOT IN (1,3,5,'thks') | 10 NOT IN (1,0,NULL,'thks') |
+----------------------------+-----------------------------+
| NULL | NULL |
+----------------------------+-----------------------------+
1 row in set, 1 warning (0.00 sec)mysql> SELECT NULL NOT IN (1,3,5,'thks'),10 NOT IN (1,10,NULL,'thks');
+----------------------------+------------------------------+
| NULL NOT IN (1,3,5,'thks') | 10 NOT IN (1,10,NULL,'thks') |
+----------------------------+------------------------------+
| NULL | 0 |
+----------------------------+------------------------------+
1 row in set (0.00 sec)
根据(3)NULL在NOT IN 的其中一侧的结果,这就可以看出问题
先来查询下面SQL语句,慢慢发现问题
SELECT p_id
FROM tree
GROUP BY p_id
上面查询结果包含了NULL值
所以查询下面SQL语句就查不到任何东西,这是因为NOT IN返回了NULL
SELECT id
FROM tree
WHERE id NOT IN (SELECT p_idFROM treeGROUP BY p_id)
所以要想查询出来结果就要先把NULL值给处理掉!好了,Bug搞定!
这题还有另外一种做法:
SELECT id,(
CASE WHEN tree.p_id IS NULL THEN 'Root'WHEN tree.id IN (SELECT p_idFROM treeGROUP BY p_id) THEN 'Inner'ELSE 'Leaf'
END
)TYPE
FROM tree
为什么是对的?留给大家想想
MySQL条件查询IN和NOT IN左右两侧包含NULL值的处理方式相关推荐
- MySQL 条件查询 limit、in、between and、like等等
MySQL 条件查询 环境: CREATE TABLE `test_user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',`userna ...
- MySQL学习-MySQL条件查询
MySQL条件查询 操作的表 1.条件查询概述 2.条件查询between and] 3.条件查询is null和is not null 4.and和or的优先级的问题 5.条件查询in 6.模糊查询 ...
- Mysql 条件查询(like、between、and、in······)
目录 Mysql 条件查询 示例 一.比较运算和逻辑运算符符 二.范围运算符 三.列表运算符 四.模糊匹配符 五.空值判断符 Mysql 条件查询 Mysql 条件查询即where子句后跟条件 运算符 ...
- mysql不等于条件不包含NULL值问题
mysql不等于条件不包含NULL值问题 table表中,type为1(100条记录).2(50条记录).NULL(50条记录) 查询:select * form table where type & ...
- MySQL 条件查询
MySQL SELECT,可以使用 WHERE 子句来指定查询条件,从 FROM 子句的中间结果中选取适当的数据行,达到数据过滤的效果. 语法格式如下: WHERE <查询条件> {< ...
- mysql 条件查询分页_百万数据下mysql条件查询及分页查询的注意事项
接上一节<百万数据mysql分页问题>,我们加上查询条件:select id from news where cate = 1 order by id desc limit 500000 ...
- MySQL 条件查询
一.带关系运算符的查询 在select语句中最常见的格式如下: select 字段名1 , 字段名2,,,, from 表名 where 条件表达式 举例,查询表student中id=4的学生姓名,过 ...
- MySQL条件查询语句(一)
条件查询 注意:条件查诟需要用到 where 询句,where 必须放到 from 询句表的后面: 执行顺序:先from再where过滤后再检索出来. 1..支持如下运算 2.等号(=)操作符 (1) ...
- php mysql 条件查询语句_where 查询条件-Medoo - 高效的轻量级PHP数据库框架, 提高开发效率!...
WHERE 语句 SQL中使用where可能会有一些不安全的动态参数传入或者一些复杂的SQL语句,但是Medoo提供非常简介和安全的方法来实现这些. 基础使用 在基础使用中. 你可以使用一些符号对参数 ...
- 有条件了!筛选,MySQL条件查询SELECT-WHERE
1.基本语法 SELECT查询列表 FROM表名 WHERE筛选表达式; 2.按条件表达式筛选 条件运算符:>,<,=,!=,<>,>=,<= 条件运算符不能判断n ...
最新文章
- 传感器c语言开发,Android环境传感器开发教程
- WPF对象级资源的定义与查找
- aspnet中gridview文本只显示开始几个文本_软网推荐:三个小软件 轻松解决文本操作难题...
- mac 下终端 操作svn命令 以及出现证书错误的处理方法
- 【javascript】不刷新页面,实时显示当前时间
- XML Schema是什么
- 哥大计算机专业 世界排名,哥伦比亚大学计算机科学硕士排名第16(2020年TFE Times排名)...
- php 实现贪吃蛇游戏,HTML5 贪吃蛇游戏实现思路及源代码_html5教程技巧
- CentOS下调整VolGroup-lv_root分区大小
- FPGA UART总线协议简介
- 收费最低的云存储_营业收费系统|自来水管理系统|自来水公司收费管理系统|手机移动抄表|网上营业厅|短信服务平台...
- 纳米软件案例之陶瓷样品测试系统,原位观察力学测试纳米压痕仪-扫描电子显微镜SEM联用...
- 在ADF应用中,能够通过 oracle.adf.view.rich.security.FRAME_BUSTING 参数来使用framebusting功能。
- V831 MP4播放+船新版本
- 高级商务办公软件应用【9】
- [附源码]Python计算机毕业设计调查问卷及调查数据统计系统
- 程序员,停止你的焦虑
- alpha和color key
- UVA 12576 - Simply Loopy
- SpringSecurity启动器
热门文章
- 老男孩爬虫实战密训课第一季,2018.6,初识爬虫训练-实战2-自动登陆抽屉网
- 点击选择-图片添加对号(单选)
- uniapp快速入门开发
- 买火车票的过来看看,提供一个小工具,不一定能买到票,但是可以实现自动登录,自动刷票,自动重新提交订单!...
- excel最常用的快捷键大全:
- 优雅写代码的45个小技巧
- export default (imported as router) was not found_一篇文章搞定as四大用法
- UOJ #449. 【集训队作业2018】喂鸽子
- 常用密码技术-对称加密
- Transition过渡动画