SQL中EXISTS和IN的区别?

Kra*_*ntz 430 sql

SQL中的EXISTSIN子句有什么区别?

我们应该何时使用EXISTS,何时使用IN

Kei*_*ith 220

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 ... )
Run Code Online (Sandbox Code Playgroud)

这在if条件语句中非常有用,因为它exists可以快得多count.

in是最好的使用,你有一个静态列表通过:

 select * from [table]
 where [field] in (1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

当你在一个in声明中有一个表时,使用a更有意义join,但大多数情况下它并不重要.查询优化器应该以任一方式返回相同的计划.在某些实现中(大多数较旧,如Microsoft SQL Server 2000),in查询将始终获得嵌套连接计划,而join查询将根据需要使用嵌套,合并散列.更现代的实现更加智能,即使在in使用时也可以调整计划.

  • 你能否详细说明"当你在in语句中有一个表时,使用连接更有意义,但这并不重要.查询优化器将以任何一种方式返回相同的计划."?不是查询优化器部分,您可以使用`JOIN`替换`IN`的部分. (2认同)
  • 好的,我应该在select子句中指定列,但是你应该更新你的答案,因为它清楚地说明查询"将以任何方式返回相同的计划". (2认同)

Mat*_*ton 123

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

SELECT * 
FROM Orders o 
WHERE EXISTS (
    SELECT * 
    FROM Products p 
    WHERE p.ProductNumber = o.ProductNumber)
Run Code Online (Sandbox Code Playgroud)

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

SELECT * 
FROM Orders 
WHERE ProductNumber IN (1, 10, 100)
Run Code Online (Sandbox Code Playgroud)

您还可以将查询结果与IN子句一起使用,如下所示:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0)
Run Code Online (Sandbox Code Playgroud)

  • @ user2054927如果子查询没有返回任何行,则上次查询将正确返回任何行 - 没有任何危险! (38认同)
  • 上次查询很危险,因为在子查询不返回任何结果的情况下它可能会失败.'in'子句至少需要1个参数... (3认同)

小智 80

根据规则优化:

  • EXISTSIN当子查询结果非常大时,速度要快得多.
  • INEXISTS当子查询结果非常小时,速度快于.

基于成本优化器:

  • 没有区别.

  • 您的论证证明?我不认为IN会比EXISTS更快! (21认同)
  • @Nawaz为什么IN总是比EXISTS慢? (21认同)
  • @LukasEder 人们喜欢直接的答案,即使这会损害正确性。比较“茶是健康的”与“研究人员声称,如果每天喝三到四杯茶,喝茶可以将患 2 型糖尿病的几率降低高达 25%。但是,喝超过四杯茶研究发现,每天喝茶会增加女性患类风湿性关节炎的风险。” (4认同)
  • 糟糕的查询优化器?我看起来像这样(虽然不是这种情况)发生在某些RDBM中...... (2认同)
  • EXISTS 返回纯布尔值,这总是比比较大于 BIT/布尔类型的字符串或值要快。IN 可能是也可能不是布尔比较。由于编程更喜欢使用 EXPLICIT 来保持稳定性(ACID 的一部分),因此通常首选 EXISTS。 (2认同)
  • 为什么这么多次被投票?绝对没有理由为什么这种基于假设的陈述应该是正确的. (2认同)

ang*_*son 40

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

这是一个公平的假设吗?


编辑:我问的原因是,在许多情况下,您可以重写基于IN的SQL以使用EXISTS,反之亦然,对于某些数据库引擎,查询优化器将以不同方式处理这两者.

例如:

SELECT *
FROM Customers
WHERE EXISTS (
    SELECT *
    FROM Orders
    WHERE Orders.CustomerID = Customers.ID
)
Run Code Online (Sandbox Code Playgroud)

可以改写为:

SELECT *
FROM Customers
WHERE ID IN (
    SELECT CustomerID
    FROM Orders
)
Run Code Online (Sandbox Code Playgroud)

或者加入:

SELECT Customers.*
FROM Customers
    INNER JOIN Orders ON Customers.ID = Orders.CustomerID
Run Code Online (Sandbox Code Playgroud)

所以我的问题仍然存在,是原始海报想知道IN和EXISTS做了什么,以及如何使用它,或者他是否要求使用IN来重写SQL而不是使用EXISTS,反之亦然?

  • 我不知道OP,但我想回答这个问题!什么时候我应该使用EXISTS代替IN与返回ID的子查询? (12认同)
  • 在`JOIN`中,你需要一个`DISTINCT` (8认同)
  • 伟大的示范,但几乎没有答案的问题 (4认同)

Ali*_*ali 28

  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'
    
    Run Code Online (Sandbox Code Playgroud)
  2. 查询1

    SELECT
    FROM    t1 
    WHERE   not  EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
    
    Run Code Online (Sandbox Code Playgroud)

    查询2

    SELECT t1.* 
    FROM   t1 
    WHERE  t1.id not in (SELECT  t2.t1id FROM t2 )
    
    Run Code Online (Sandbox Code Playgroud)

    如果t1你的id中有null值,那么Query 1会找到它们,但是查询2无法找到null参数.

    我的意思是IN无法与null进行比较,因此它没有null的结果,但EXISTS可以将所有内容与null进行比较.


小智 16

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


小智 9

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

SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)
Run Code Online (Sandbox Code Playgroud)

IN效率低下这么Exists快.


Dav*_*itz 9

IN仅支持相等关系(或以NOT开头时的不等式).
它是= any/= some的同义词,例如

select    * 
from      t1 
where     x in (select x from t2)
;
Run Code Online (Sandbox Code Playgroud)

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 || '?'
                  )
;
Run Code Online (Sandbox Code Playgroud)

另外还有一点 -

据称EXISTSIN之间的性能和技术差异可能来自特定供应商的实施/限制/错误,但很多时候它们只不过是因为对数据库内部缺乏了解而产生的神话.

表的定义,统计信息的准确性,数据库配置和优化程序的版本都会对执行计划产生影响,从而影响性能指标.

  • 支持您对性能的评论:在不关注特定 DBMS 的情况下,我们应该假设由优化器来找出最有效的方法。 (2认同)

Gis*_*shu 5

我认为,

  • EXISTS是什么时候需要将查询结果与另一个子查询匹配.在SubQuery结果匹配的情况下,需要检索查询#1结果.加入的种类..例如,选择已下订单#2的客户表#1

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

什么时候使用一个...当你觉得它读得合适时(更好地传达意图).