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

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


当前回答

EXISTS is much faster than IN when the subquery results is very large. IN is faster than EXISTS when the subquery results is very small. 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' Query 1 SELECT FROM t1 WHERE not EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id) Query 2 SELECT t1.* FROM t1 WHERE t1.id not in (SELECT t2.t1id FROM t2 ) If in t1 your id has null value then Query 1 will find them, but Query 2 cant find null parameters. I mean IN can't compare anything with null, so it has no result for null, but EXISTS can compare everything with null.

其他回答

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

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

一般的经验法则是,如果子查询包含一个较大的 对于大量的数据,EXISTS操作符提供了更好的性能。 但是,如果使用IN操作符,查询将执行得更快 子查询返回的结果集非常小。

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

基于规则优化器:

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

基于成本优化器:

没有区别。

我假设您知道它们的作用,因此使用方式不同,所以我将把您的问题理解为:什么时候重写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,反之亦然,将是一个好主意?

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

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