有两个表,就叫作源表和目标表吧。它们有一个相同的字段,通过该字段可以把源表和目标表关联在一起,我们希望从源表中检索到的记录里的关联字段的值没有存在目标表中。举个例子,源表 dept,目标表 emp,获取 dept 表中部门编号不在 emp 表中的记录。检查两张表的数据,我们发现 emp 表中没有部门编号 40 的数据。

图1 emp 表的数据
图2 dept 表的数据

实现这种的查询的方法有很多,不同的实现方式的性能也会不一样。我们就来看看都有哪些方法?

NOT IN

SELECT *
FROMdept
WHERE deptno NOT IN (SELECT deptno FROMemp)

这种实现方式需要注意一个点,就是在 not in 里面不能出现 NULL,如果出现 NULL 就会查不到结果。比如下面这条 SQL,没有数据返回。

SELECT dname
FROMdept
WHERE deptno NOT IN (SELECT deptno FROMemp UNION ALL SELECT NULL)

为什么是这样呢?

因为在逻辑运算中,涉及到 NULL 的操作的结果仍为 NULLnot 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
FROMemp
UNION ALL
SELECT NULL)
SELECT *
FROMdept
WHERE NOT EXISTS (SELECT NULL FROMe WHERE e.deptno = dept.deptno)

使用 not exists 的 SQL 的一般形式:

SELECT 选择列
FROM源表
WHERE NOT EXISTS (SELECT NULL FROM目标表 WHERE 关联字段)

在 MySQL 5.6 之前,子查询的性能表现得比较差,因而就有人想着把子查询改成连接的方式以提高查询性能。

LEFT JOIN

通常,我们会想到使用 NOT INNOT EXISTS 做排除操作。其实,使用 LEFT JOIN 也可以达到相同的目的。

SELECT d.*
FROMdept 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 表中的数据。

总结

  1. 使用 not in 时要考虑到排除的值中是否有 NULL ,如果有,需要提前做过滤处理。
  2. not existsleft join 都可以用来做排除操作,可以任选一种方式实现,如果 SQL 的性能表现不佳,则可以换另外一种方式试试。

来源:SQL实现

作者:zero

原文:编写 SQL 的排除联接

select * 排除字段_编写 SQL 的排除联接相关推荐

  1. mysql写出总分最高的学生姓名_编写SQL语句查询出每个各科班分数最高的同学的名字,班级名称,课程名称,分数...

    这个问题是在csdn上一位朋友写的,但是答案有点复杂,而且查询使用的效率也不是很好,于是自己也写了一个.以下是表结构和数据, 有以下两张表, Class表 classid classname 1 高三 ...

  2. sql查询每科成绩的最高分_编写SQL语句查询出每个各科班分数最高的同学的名字,班级名称,课程名称,分数...

    这个问题是在csdn上一位朋友写的,但是答案有点复杂,而且查询使用的效率也不是很好,于是自己也写了一个.以下是表结构和数据, 有以下两张表, Class表 classid classname 1 高三 ...

  3. mysql查询排除字段_mysql查询表,指定排除字段

    查询user表中除email以外的所有字段 假设数据库bbs中有user表,字段如下 id,username,password,gender,email ----------------------- ...

  4. mongoose 批量修改字段_常用SQL系列之(五):多表和禁止插入、批量与特殊更新等...

    本系统为@牛旦教育IT课堂在微头条上的内容, 为便于查阅,特辑录于此,都是常用SQL基本用法.. 前两篇连接: (一):SQL点滴(查询篇):数据库基础查询案例实战 (二):SQL点滴(排序篇):数据 ...

  5. 用SQL语句添加删除修改字段_常用SQL

    1.增加字段      alter table docdsp     add dspcode char(200) 2.删除字段      ALTER TABLE table_NAME DROP COL ...

  6. mysql select内部原理_数据库SQL SELECT查询的工作原理

    作为Web开发人员,虽并非专业的DBA,但我们总是离不开数据库.一般开发员只会应用SQL的四条经典语句:select,insert,delete,update.以至于从来没有研究过它们的工作原理,在这 ...

  7. select * 排除字段_interesting数据库查找语句Select还能这样用

    Navicat Premium是一个可连接多种数据库的管理工具,它可以让你以单一程序同时连接到MySQL.Oracle及PostgreSQL数据库,让管理不同类型的数据库更加的方便. 不久前,我们探索 ...

  8. 排除字段重复行的SQL

    排除字段重复行的SQL -- if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[test]') and OBJ ...

  9. fastjson 不转某些字段_全面总结Fastjson过滤字段、排除字段的5种方法(含示例)...

    1.通过注解指定不需要序列化的字段 在不需要序列化的字段,添加@JSONField(serialize = false)注解可进行排除. public class DontSerializeAnnot ...

最新文章

  1. 基于NHibernate的三层结构应用程序开发初步
  2. 并发编程-volatile和synchronized的区别
  3. 【信号】函数kill、raise、abort、alarm
  4. 调试opengl程序出错
  5. 【原创翻译】生动详细解释javascript的冒泡和捕获,包懂包会
  6. ubuntu上 grafana + influxdb + telegraf 安装配置
  7. HTTPS科普扫盲帖【转】
  8. jQuery课堂测验
  9. paip.docfile二进制复合文档
  10. 微软模拟飞行2020服务器多少内存,《微软模拟飞行2020》:一款游戏大到7000万GB,这才是真正的模拟地球?!...
  11. 数据库.数据库管理系统.数据库系统三者之间的关系
  12. 柚鸥ASO优化:aso搜索优化怎么做
  13. java模拟器怎么打开apk文件,APK是什么 APK文件怎么打开【详解】
  14. Java项目:学生综合素质评价系统(java+SSM+thymeleaf+layui+Mysql)
  15. 海思HI3516A千兆网卡换百兆网卡配置方法
  16. 胆囊结石与什么因素有关
  17. 统一网关Gateway-搭建网关服务
  18. 词向量系列之One-Hot编码详解
  19. varchar 和 char 的区别
  20. 极简linux版本,4MLinux 26.0发布,这是一个极简版本

热门文章

  1. 云函数查询_速览 | 京东云5月重要产品与功能更新
  2. mysql begin operations_MySQL入门(七):More JOIN operations
  3. 怎么创建计算机快捷方式到桌面两种方法,使用脚本主机创建Windows快捷方式 - Windows Client | Microsoft Docs...
  4. android中的xml布局文件如何引用另一个xml布局文件,引用另一个layout.xml文件而不复制它...
  5. 1445.32php,nginx实现mysql的负载均衡
  6. 用python玩转数据慕课答案第三周_大学慕课用Python玩转数据答案公众号
  7. echart vue 图表大小_cesium+vue,性能优化
  8. java thread safe_Java 线程安全 Thread-Safety
  9. linux 建oracle分区表,Oracle 10g 11g分区表创建举例
  10. python模块名限定_python 正则表达式 匹配 ?的使用 限定符 sys.re模块