✅exists和in有什么区别?如何选择?
典型回答
exist和in都是SQL中用于子查询的,他们主要的区别就是实际执行中的执行逻辑的差别,之所以放在一起比较是因为他们通常可以实现同样的功能。
比如说查询所有工作地在北京的员工,如果员工表中并没有具体的地址,而只有部门的id,而部门表中才有地址名称的时候,可以用以下方式实现这个功能:
SELECT *
FROM employees e
WHERE e.dept_id IN (
SELECT d.id FROM departments d WHERE d.location = 'Beijing'
);** in可以用来判断某个值是否在一个结果集里。**
和
SELECT *
FROM employees e
WHERE EXISTS (
SELECT 1 FROM departments d WHERE d.location = 'Beijing' AND d.id = e.dept_id
);exists用来判断子查询是否返回至少一行数据。
他们之间有以下几个区别:
1、在使用in做子查询的时候,通常不需要关联条件,而使用exists的时候,需要有一个关联条件,如d.id = e.dept_id
- in之所以不需要关联条件,是因为在in的过程中其实就是在做关联条件的判断了,即用e.dept_id和子查询中返回的d.id的结果集做值匹配。
2、in后面要跟的是一个结果集,in (xxx),这里的xxx就要是一个结果集,如id的列表。而exists后面要跟的是一个布尔值(true or false),exist (xxx),这里的xxx就是一个布尔判断,true 或者 false。
3、in和exist的执行逻辑是不一样的
- in的执行逻辑是,它先执行内部子查询,得到一个结果集。然后,它对外部查询中的每一行,检查该行的指定列值是否存在于这个结果集中。
- exist的执行逻辑是,它对外部查询中的每一行,都通过关联条件(
**<font style="color:rgb(64, 64, 64);">d.id = e.dept_id</font>**)执行一次关联子查询。只要子查询对于当前外部行返回至少一行记录,**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">EXISTS</font>**就立即返回**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">TRUE</font>**,则认为匹配成功。
那么如何选择呢?
1、如果外部表(例子中的employees表)非常大,建议用IN。因为<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">EXISTS</font> 需要为外部表的每一行执行一次子查询。如果子查询本身不高效(比如缺少索引),这会非常慢。而<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">IN</font> 只执行一次子查询,其性能瓶颈主要在子查询结果集生成和后续的查找上。
2、如果子查询返回的结果(例子中的departments在北京的查询结果)比较大,那么建议用EXISTS,因为IN的话会有部分结果集生成的成本。