481

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

我们应该什么时候使用EXISTS,什么时候应该使用IN

4

21 回答 21

239

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有条件语句时最有用,因为exists它比count.

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

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

当您在语句中有一个表时in,使用 a 更有意义join,但大多数情况下它应该无关紧要。无论哪种方式,查询优化器都应该返回相同的计划。在某些实现中(大多数是较旧的,例如 Microsoft SQL Server 2000)in查询将始终获得嵌套连接计划,而join查询将酌情使用嵌套、合并散列。更现代的实现更智能,即使在in使用时也可以调整计划。

于 2008-08-24T09:37:52.493 回答
146

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)
于 2008-08-24T08:47:45.967 回答
88

基于规则优化器

  • EXISTSIN当子查询结果非常大时,比 快得多。
  • IN比 快EXISTS,当子查询结果很小的时候。

基于成本优化器

  • 没有区别。
于 2010-10-19T01:35:32.520 回答
45

我假设您知道它们的作用,因此使用方式不同,因此我将您的问题理解为:何时重写 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
)

或加入:

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

所以我的问题仍然存在,原始发帖人是否想知道 IN 和 EXISTS 的作用,以及如何使用它,或者他是否问是否使用 IN 重写 SQL 以使用 EXISTS ,反之亦然,这将是一个好主意吗?

于 2008-08-24T08:45:39.717 回答
31
  1. EXISTSIN比子查询结果非常大时快得多。
    INEXISTS子查询结果非常小时要快。

    CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
    GO
    CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
    GO
    
    INSERT INTO t1
    SELECT 1, 'title 1', 5 UNION ALL
    SELECT 2, 'title 2', 5 UNION ALL
    SELECT 3, 'title 3', 5 UNION ALL
    SELECT 4, 'title 4', 5 UNION ALL
    SELECT null, 'title 5', 5 UNION ALL
    SELECT null, 'title 6', 5
    
    INSERT INTO t2
    SELECT 1, 1, 'data 1' UNION ALL
    SELECT 2, 1, 'data 2' UNION ALL
    SELECT 3, 2, 'data 3' UNION ALL
    SELECT 4, 3, 'data 4' UNION ALL
    SELECT 5, 3, 'data 5' UNION ALL
    SELECT 6, 3, 'data 6' UNION ALL
    SELECT 7, 4, 'data 7' UNION ALL
    SELECT 8, null, 'data 8' UNION ALL
    SELECT 9, 6, 'data 9' UNION ALL
    SELECT 10, 6, 'data 10' UNION ALL
    SELECT 11, 8, 'data 11'
    
  2. 查询 1

    SELECT
    FROM    t1 
    WHERE   not  EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
    

    查询 2

    SELECT t1.* 
    FROM   t1 
    WHERE  t1.id not in (SELECT  t2.t1id FROM t2 )
    

    如果t1您的 id 中有 null 值,则查询 1 会找到它们,但查询 2 找不到 null 参数。

    我的意思是IN不能将任何内容与 null 进行比较,因此它没有 null 的结果,但EXISTS可以将所有内容与 null 进行比较。

于 2012-07-04T12:40:45.590 回答
18

如果您使用IN运算符,SQL 引擎将扫描从内部查询获取的所有记录。另一方面,如果我们使用EXISTS,SQL 引擎将在找到匹配项后立即停止扫描过程。

于 2013-07-16T08:00:48.980 回答
13

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 || '℅'
                  )
;

换个说法——

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

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

于 2016-10-07T13:46:27.513 回答
10

Exists关键字评估真或假,但关键字比较相应子查询列中的IN所有值。另一个Select 1可以与Exists命令一起使用。例子:

SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)

但是IN效率较低所以Exists速度更快。

于 2012-05-25T05:00:44.210 回答
5

我认为,

  • EXISTS是当您需要将查询结果与另一个子查询匹配时。Query#1 结果需要在 SubQuery 结果匹配的地方检索。一种加入..例如选择客户表#1 谁也下了订单表#2

  • IN 用于检索特定列的值是否位于IN列表 (1,2,3,4,5) 例如选择位于以下邮政编码中的客户,即邮政编码值位于 (....) 列表中。

何时使用一个而不是另一个......当你觉得它读得恰当时(更好地传达意图)。

于 2008-08-24T08:50:31.497 回答
3

哪个更快取决于内部查询获取的查询数量:

  • 当您的内部查询获取数千行时, EXIST 将是更好的选择
  • 当您的内部查询获取几行时,IN 会更快

EXIST 评估 true 或 false 但 IN 比较多个值。当您不知道该记录是否存在时,您应该选择 EXIST

于 2013-07-04T07:08:17.110 回答
3

据我所知,当子查询返回一个NULL值时,整个语句变为NULL. 在这种情况下,我们使用EXITS关键字。如果我们想比较子查询中的特定值,那么我们使用IN关键字。

于 2012-03-21T02:01:15.587 回答
3

区别就在这里:

select * 
from abcTable
where exists (select null)

上面的查询将返回所有记录,而下面的查询将返回空。

select *
from abcTable
where abcTable_ID in (select null)

试一试并观察输出。

于 2015-05-19T12:42:56.670 回答
3

原因是 EXISTS 运算符基于“至少找到”原则工作。一旦找到至少一个匹配的行,它就会返回 true 并停止扫描表。

另一方面,当 IN 运算符与子查询组合时,MySQL 必须先处理子查询,然后使用子查询的结果来处理整个查询。

一般的经验法则是,如果子查询包含大量数据,则 EXISTS 运算符提供更好的性能。

但是,如果从子查询返回的结果集非常小,则使用 IN 运算符的查询将执行得更快。

于 2016-04-07T09:04:10.500 回答
2

In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.

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

于 2017-08-17T14:10:53.087 回答
1

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

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

至于布尔值与比较器参数,要生成布尔值,需要比较两个值,这就是任何 if 条件的工作原理。所以我无法理解 IN 和 EXISTS 的行为方式有何不同。

于 2016-09-12T22:02:00.877 回答
0

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

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

于 2012-12-04T11:24:04.720 回答
0

我相信这有一个直截了当的答案。您为什么不从在他们的系统中开发该功能的人那里检查它?

如果您是 MS SQL 开发人员,这里是直接来自 Microsoft 的答案。

IN

确定指定值是否与子查询或列表中的任何值匹配。

EXISTS

指定一个子查询来测试是否存在行。

于 2017-03-24T05:01:10.603 回答
0

如果您可以使用where in而不是where exists,那么where in可能会更快。

使用where inorwhere exists 将遍历您父结果的所有结果。这里的不同是where exists会导致很多dependet子查询。如果您可以防止依赖子查询,那么where in将是更好的选择。

例子

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

以下查询 usingwere exists的执行时间为 141 毫秒:

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

发生这种情况是因为每个用户都会执行一个依赖子查询: 在此处输入图像描述

但是,如果我们避免存在查询并使用以下方法编写它:

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

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

在此处输入图像描述

于 2021-11-06T15:12:27.007 回答
0

我发现使用 EXISTS 关键字通常很慢(这在 Microsoft Access 中非常正确)。我改为以这种方式使用连接运算符: should-i-use-the-keyword-exists-in-sql

于 2017-06-27T14:54:58.753 回答
-1

EXISTS 的性能比 IN 快。如果大多数过滤条件在子查询中,那么最好使用 IN,如果大多数过滤条件在主查询中,那么最好使用 EXISTS。

于 2013-04-09T19:03:43.103 回答
-2

如果您使用 IN 运算符,SQL 引擎将扫描从内部查询获取的所有记录。另一方面,如果我们使用 EXISTS,SQL 引擎将在找到匹配项后立即停止扫描过程。

于 2012-06-04T01:43:38.290 回答