本题目的:学习如何使用exists

用法:

select * from table_name where [not] exists(子查询);

exists的执行过程:

  1. 首先查询select * from table_name的结果。
  2. 将外查询的结果按行代入到子查询,看子查询有没有结果。
  3. 子查询有结果,exists返回true,not exists返回false;子查询无结果,exists返回false,not exists返回true。
  4. 返回true则将代入行显示出来,返回false则将带入行隐藏(不显示)。
  5. 当外查询的结果按行全部代入到子查询中,得到的新的查询结果即该语句的查询结果。

in的执行过程:


  1. 先运行子查询,生成结果集。
  2. 再运行外查询时,判断col_name在不在子查询里,在的话则返回该行,不在则不返回。
  3. col_name的列数和子查询的列数要相对应。

区别:

对于同一个问题,in和exists是两种不同的检索方式,他们写出来的逻辑方式也是不同的。in是先把子表的内容查下来,放在内存里面,然后让外表一个个匹配。exists是直接让内外表联结匹配合适的。
exists最大的优势是子查询和外部的表是能够逻辑清晰地用where联结的,然后根据联结结果判断是True还是False。
理论上in和exists匹配的次数应该是一样的,但是exists只需要匹配到就行,这样就不只是根据笛卡尔积来做了,如果内表里面加上一些索引什么的,可以让exists的查询次数=外表行数。当然in的优势是内存里比较比直接从数据库里面联结快。所以这个问题要具体问题具体分析。根据相关条件涉及的字段的索引情况和数据量多少,一般认为效率不如exists。一般编程习惯应该是用exists而不用in,而很少去考虑in和exists的执行效率。
另外,in和exists他们两个的效率一般有个口诀:
  • 当外大子小时,即查询的内容很大时,判断次数少,in优于exist【子查询小用in】
  • 当外小子大时,即查询内容很小时,代入次数少,exists优于in【子查询大用exists】
关于这个效率的问题,可以参考这篇文章:https://blog.csdn.net/fmwind/article/details/103874612

本题答案:

select e.*
from employees as e
where not exists (select emp_no from dept_emp as d where e.emp_no = d.emp_no);