SQL中的EXISTS子句和IN子句有什么区别?

什么时候应该使用EXISTS,什么时候应该使用IN?


当前回答

在某些情况下,使用In比使用EXISTS更好。通常,如果选择谓词在子查询中,则使用In。如果选择谓词在父查询中,则使用EXISTS。

https://docs.oracle.com/cd/B19306_01/server.102/b14211/sql_1016.htm#i28403

其他回答

IN只支持平等关系(或前面有NOT的不平等关系)。 它是=any / =some的同义词

select    * 
from      t1 
where     x in (select x from t2)
;

EXISTS支持不能用IN表示的不同类型的关系,例如-

select    * 
from      t1 
where     exists (select    null 
                  from      t2 
                  where     t2.x=t1.x 
                        and t2.y>t1.y 
                        and t2.z like '℅' || t1.z || '℅'
                  )
;

还有另一种说法——

exist和IN之间所谓的性能和技术差异可能是由于特定供应商的实现/限制/错误造成的,但很多时候它们只是由于缺乏对数据库内部结构的理解而产生的神话。

表的定义、统计数据的准确性、数据库配置和优化器的版本都会影响执行计划,因此也会影响性能指标。

我的理解是,只要我们不处理NULL值,两者都应该是相同的。

同样的原因,查询不返回值for = NULL vs is NULL。 http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/

至于布尔和comparator参数,为了生成一个布尔值,两个值都需要进行比较,这就是任何if条件的工作方式。所以我不明白IN和EXISTS的行为有什么不同 .

如果你可以用where in代替where exists,那么where in可能更快。

使用where in或where exists 将遍历父结果的所有结果。不同之处在于where exists将导致大量依赖子查询。如果你可以防止依赖子查询,那么where in将是更好的选择。

例子

假设我们有10,000家公司,每家公司有10个用户(因此我们的用户表有100,000个条目)。现在假设您希望通过用户名或公司名查找用户。

下面使用were exists查询的执行时间为141ms:

select * from `users` 
where `first_name` ='gates' 
or exists 
(
  select * from `companies` 
  where `users`.`company_id` = `companies`.`id`
  and `name` = 'gates'
)

这是因为对每个用户执行一个依赖子查询:

然而,如果我们避免exists查询并使用:

select * from `users` 
where `first_name` ='gates' 
or users.company_id in  
(
    select id from `companies` 
    where  `name` = 'gates'
)

然后避免依赖子查询,查询将在0,012毫秒内运行

如果子查询返回多个值,则可能需要执行外层查询—如果条件中指定的列中的值与子查询结果集中的任何值匹配。要执行此任务,需要使用in关键字。

您可以使用子查询来检查一组记录是否存在。为此,您需要使用exists子查询子句。exists关键字总是返回true或false值。

我假设您知道它们的作用,因此使用方式不同,所以我将把您的问题理解为:什么时候重写SQL以使用IN而不是EXISTS是一个好主意,或者反之亦然。

这个假设合理吗?


编辑:我问的原因是,在许多情况下,您可以重写基于in的SQL来使用EXISTS,反之亦然,对于某些数据库引擎,查询优化器将区别对待这两者。

例如:

SELECT *
FROM Customers
WHERE EXISTS (
    SELECT *
    FROM Orders
    WHERE Orders.CustomerID = Customers.ID
)

可以改写为:

SELECT *
FROM Customers
WHERE ID IN (
    SELECT CustomerID
    FROM Orders
)

或者用join:

SELECT Customers.*
FROM Customers
    INNER JOIN Orders ON Customers.ID = Orders.CustomerID

所以我的问题仍然存在,原来的海报想知道什么是IN和EXISTS,因此如何使用它,或者他问是否重写SQL使用IN使用EXISTS,反之亦然,将是一个好主意?