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

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


当前回答

如果你可以用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毫秒内运行

其他回答

EXISTS将告诉您查询是否返回了任何结果。例如:

SELECT * 
FROM Orders o 
WHERE EXISTS (
    SELECT * 
    FROM Products p 
    WHERE p.ProductNumber = o.ProductNumber)

IN用于将一个值与多个值进行比较,并且可以使用文字值,如下所示:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (1, 10, 100)

你也可以用IN子句来使用查询结果,就像这样:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0)

我认为,

EXISTS是当您需要将查询结果与另一个子查询匹配时。 查询#1的结果需要在SubQuery结果匹配的地方检索。有点像Join.. 例如,选择表1中也下过表2订单的客户 IN用于检索特定列的值是否位于列表(1,2,3,4,5)中 例如,选择位于以下邮政编码中的客户,即zip_code值位于(....)列表中。

什么时候使用一种而不是另一种……当你觉得读起来合适的时候(更好地传达意图)。

exists关键字可以这样使用,但实际上它是为了避免计数:

--this statement needs to check the entire table
select count(*) from [table] where ...

--this statement is true as soon as one match is found
exists ( select * from [table] where ... )

这是最有用的if条件语句,as exists可以比count快得多。

in最好用在你有一个静态列表要传递的地方:

 select * from [table]
 where [field] in (1, 2, 3)

当在in语句中有一个表时,使用连接更有意义,但大多数情况下这并不重要。无论哪种方式,查询优化器都应该返回相同的计划。在一些实现中(大多数是旧的,如Microsoft SQL Server 2000),查询将总是获得嵌套的连接计划,而连接查询将适当地使用嵌套、合并或散列。更现代的实现更智能,甚至可以在使用in时调整计划。

如果你可以用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只支持平等关系(或前面有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之间所谓的性能和技术差异可能是由于特定供应商的实现/限制/错误造成的,但很多时候它们只是由于缺乏对数据库内部结构的理解而产生的神话。

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