Skip to content

面试速答(先看这里)

**一句话结论:**exist和in都是SQL中用于子查询的,他们主要的区别就是实际执行中的执行逻辑的差别,之所以放在一起比较是因为他们通常可以实现同样的功能。

60秒标准回答:

exist和in都是SQL中用于子查询的,他们主要的区别就是实际执行中的执行逻辑的差别,之所以放在一起比较是因为他们通常可以实现同样的功能

比如说查询所有工作地在北京的员工,如果员工表中并没有具体的地址,而只有部门的id,而部门表中才有地址名称的时候,可以用以下方式实现这个功能

in可以用来判断某个值是否在一个结果集里

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**比如说查询所有工作地在北京的员工,如果员工表中并没有具体的地址,而只有部门的id,而部门表中才有地址名称的时候,可以用以下方式实现这个功能:
  • **要点2:**exists用来判断子查询是否返回至少一行数据。
  • **要点3:**1、在使用in做子查询的时候,通常不需要关联条件,而使用exists的时候,需要有一个关联条件,如 d.id = e.dept_id
  • **要点4:**2、in后面要跟的是一个结果集, in (xxx) ,这里的xxx就要是一个结果集,如id的列表。
  • **要点5:**1、如果外部表(例子中的employees表)非常大,建议用IN 。

**记忆锚点:**EXISTS → exists → exist → xxx → edept_id → did

关键取舍:

  • 而 IN 只执行一次子查询,其性能瓶颈主要在子查询结果集生成和后续的查找上。

加分表达:

  • 比如说查询所有工作地在北京的员工,如果员工表中并没有具体的地址,而只有部门的id,而部门表中才有地址名称的时候,可以用以下方式实现这个功能: in可以用来判断某个值是否在一个结果集里。
  • 只要子查询对于当前外部行返回至少一行记录, EXISTS 就立即返回 TRUE ,则认为匹配成功。
  • 1、如果外部表(例子中的employees表)非常大,建议用IN 。

追问准备:

  • 围绕「EXISTS」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「exists」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「exist」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

exist和in都是SQL中用于子查询的,他们主要的区别就是实际执行中的执行逻辑的差别,之所以放在一起比较是因为他们通常可以实现同样的功能。

比如说查询所有工作地在北京的员工,如果员工表中并没有具体的地址,而只有部门的id,而部门表中才有地址名称的时候,可以用以下方式实现这个功能:

bash
SELECT * 
FROM employees e
WHERE e.dept_id IN (
    SELECT d.id FROM departments d WHERE d.location = 'Beijing'
);

in可以用来判断某个值是否在一个结果集里。

和

bash
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的执行逻辑是,它对外部查询中的每一行,都通过关联条件(**d.id = e.dept_id**)执行一次关联子查询。只要子查询对于当前外部行返回至少一行记录,**EXISTS** 就立即返回 **TRUE**,则认为匹配成功。

那么如何选择呢?

1、如果外部表(例子中的employees表)非常大,建议用IN。因为EXISTS 需要为外部表的每一行执行一次子查询。如果子查询本身不高效(比如缺少索引),这会非常慢。而IN 只执行一次子查询,其性能瓶颈主要在子查询结果集生成和后续的查找上。

2、如果子查询返回的结果(例子中的departments在北京的查询结果)比较大,那么建议用EXISTS,因为IN的话会有部分结果集生成的成本。