编写 SQL 的排除联接
有两个表,就叫源表和目标表吧。它们有一个相同的字段,通过该字段可以把源表和目标表关联在一起,我们希望从源表中检索到的记录里的关联字段的值没有存在目标表中。举个例子,源表 dept
,目标表 emp
,获取 dept
表中部门编号不在 emp
表中的记录。在检查两张表的数据后,我们发现 emp
表中没有部门编号 40 的数据。
图1 emp 表的数
图2 dept 表的数据
实现这种的查询的方法有很多,不同的实现方式的性能也会不一样。我们就来看看都有哪些方法?
NOT IN
SELECT
*
FROM
dept
WHERE deptno NOT IN
(SELECT
deptno
FROM
emp)
这种实现方式需要注意一个点,就是在 not in
里面不能出现 NULL
,如果出现 NULL
就会查不到结果。比如下面这条 SQL,没有数据返回。
SELECT
dname
FROM
dept
WHERE deptno NOT IN
(SELECT
deptno
FROM
emp
UNION ALL
SELECT
NULL)
为什么是这样呢?
因为在逻辑运算中,涉及到 NULL
的操作的结果仍为 NULL
。not in
可以改写成 or
的形式,比如 deptno not in(10,NULL)
展开成 or
的表达式是:not (deptno = 10 or deptno = NULL)
,最终的表达式是 not NULL
。
NOT EXISTS
使用 not exists
可以避免由于目标表的关联列上出现 NULL
而查不出数据。
WITH e AS
(SELECT
deptno
FROM
emp
UNION ALL
SELECT
NULL)
SELECT
*
FROM
dept
WHERE NOT EXISTS
(SELECT
NULL
FROM
e
WHERE e.deptno = dept.deptno)
使用 not exists
的 SQL 的一般形式:
SELECT
目标列
FROM
源表
WHERE NOT EXISTS
(SELECT
NULL
FROM
目标表
WHERE 关联字段)
在 MySQL 5.6 之前,子查询的性能表现得比较差,因而就有人想着把子查询改成连接的方式以提高查询性能。
LEFT JOIN
通常,我们会想到使用 NOT IN
、NOT EXISTS
做排除操作。其实,使用 LEFT JOIN
也可以达到相同的目的。
SELECT
d.*
FROM
dept d
LEFT JOIN emp e
ON e.deptno = d.deptno
WHERE e.deptno IS NULL
对于表达式 a left join b
,不管 b 表中是否有数据可以和 a 表匹配得上,a 表总是能返回所有数据。如果 b 表中没有数据能匹配得上 a 表,在查询结果中会使用 NULL
填充 b 表的列。因此,通过过滤条件 b.关联列 is NULL
可以找到只存在于 a 表中的数据。
总结
- 使用
not in
时要考虑到排除的值中是否有NULL
,如果有,需要提前做过滤处理。 -
not exists
和left join
都可以用来做排除操作,可以任选一种方式实现,如果 SQL 的性能表现不佳,则可以换另外一种方式试试。
- 03.HTML头部/CSS/图像/表格/列表
- 巧用flashback database实现灵活的数据切换(r5笔记第9天)
- 01.HTML教程/简介/基础
- 大型分布式网站架构技术总结
- MySQL和Oracle对比之存储过程(r5笔记第7天)
- 07.Java变量类型
- OAuth 2.0验证【面试+工作】
- MySQL备份恢复第一篇(r5笔记第5天)
- 经典面试问题: Top K 之 -- 海量数据找出现次数最多或,不重复的
- Java多线程详解4【面试+工作】
- Java多线程详解5【面试+工作】
- Java多线程详解6【面试+工作】
- MySQL备份恢复第二篇(r5笔记第6天)
- SpringMVC 中配置 Swagger 插件.
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解