Answers:
该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
语句中有表时,使用会更有意义join
,但是大多数情况下都没有关系。查询优化程序应以两种方式返回相同的计划。在某些实现中(大多数是较旧的版本,例如Microsoft SQL Server 2000),in
查询将始终获得嵌套的连接计划,而join
查询将酌情使用嵌套,合并或哈希。更现代的实现更智能,即使在in
使用时也可以调整计划。
select * from [table] where [field] in (select [field] from [table2])
返回与相同的结果(和查询计划)select * from [table] join [table2] on [table2].[field] = [table].[field]
。
table
,第二个查询从table
和返回所有列table2
。在某些(大多数是较旧的)SQL数据库中,in
查询将实现为嵌套连接,而join
查询可以嵌套,合并,散列等(最快的方式)。
exists
可以在case语句中使用,因此它们也可以方便地使用,即select case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
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
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
)
或加入:
SELECT Customers.*
FROM Customers
INNER JOIN Orders ON Customers.ID = Orders.CustomerID
所以我的问题仍然存在,原始的发布者是否想知道IN和EXISTS的功能,以及如何使用它,还是他问是否还要使用IN重写SQL以使用EXISTS来代替,反之亦然,这将是一个好主意吗?
JOIN
,您将需要一个DISTINCT
EXISTS
比IN
子查询结果很大时要快得多。
IN
比EXISTS
子查询结果非常小时要快。
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'
查询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中具有空值,则查询1将找到它们,但查询2无法找到空参数。
我的意思是IN
不能将任何内容与null进行比较,因此它没有null的结果,但EXISTS
可以将所有内容与null进行比较。
如果使用的是IN
运算符,则SQL引擎将扫描从内部查询中获取的所有记录。另一方面,如果使用EXISTS
,SQL引擎将在找到匹配项后立即停止扫描过程。
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 || '℅'
)
;
EXISTS和IN之间据称的性能和技术差异可能是由特定供应商的实现/限制/错误引起的,但是很多时候,由于缺乏对数据库内部的了解,它们只是虚构的。
表的定义,统计信息的准确性,数据库配置和优化器的版本都会影响执行计划,从而影响性能指标。
区别在于:
select *
from abcTable
where exists (select null)
上面的查询将返回所有记录,而下面的查询将返回空。
select *
from abcTable
where abcTable_ID in (select null)
试试看,观察输出。
哪一个速度更快取决于内部查询获取的查询数量:
EXIST评估是对还是错,但IN比较多个值。当您不知道记录是否存在时,应选择EXIST
原因是EXISTS运算符基于“至少找到”原理进行工作。它返回true,并且一旦找到至少一个匹配的行,就停止扫描表。
另一方面,当IN运算符与子查询结合使用时,MySQL必须首先处理该子查询,然后使用该子查询的结果来处理整个查询。
一般的经验法则是,如果子查询包含大量数据,则EXISTS运算符可提供更好的性能。
但是,如果子查询返回的结果集很小,则使用IN运算符的查询将执行得更快。
我的理解是,只要我们不处理NULL值,两者应该相同。
查询不返回= NULL vs的值的相同原因是NULL。 http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
至于布尔vs比较器参数,要生成一个布尔值,需要比较两个值,这就是if条件如何工作的方式,因此我无法理解IN和EXISTS的行为方式不同。
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
我发现使用EXISTS关键字通常真的很慢(在Microsoft Access中非常正确)。我改为以这种方式使用join运算符: 我应该在SQL中使用关键字存在
如果您使用IN运算符,则SQL引擎将扫描从内部查询中获取的所有记录。另一方面,如果我们使用EXISTS,则SQL引擎在找到匹配项后将立即停止扫描过程。
IN
并且EXISTS
可以等效并彼此转化。
JOIN
代替的部分IN
。