답변:
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
하위 쿼리 결과가 매우 작을 때보 다 빠릅니다 .비용 최적화 도구를 기반으로 :
나는 그들이 당신이하는 일을 알고 따라서 다르게 사용된다고 가정하므로, 나는 당신의 질문을 다음과 같이 이해할 것입니다 : 언제 EXISTS 대신 IN을 사용하도록 SQL을 다시 작성하는 것이 좋을까요?
이것이 공정한 가정입니까?
편집 : 내가 묻는 이유는 많은 경우 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 가하는 일에 대해 궁금해하고 그것을 사용하는 방법을 알고 있습니까? 아니면 EXISTS를 대신하여 IN을 사용하여 SQL을 다시 작성하거나 그 반대의 경우에도 좋은 아이디어입니까?
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에 null 값이 있으면 Query 1이 값을 찾지 만 Query 2는 null 매개 변수를 찾을 수 없습니다.
내 말 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는 true 또는 false로 평가되지만 IN은 여러 값을 비교합니다. 기록이 존재하는지 모르는 경우 EXIST를 선택해야합니다.
그 이유는 EXISTS 연산자가 "적어도 발견 된"원칙에 따라 작동하기 때문입니다. 일치하는 행이 하나 이상 발견되면 true를 리턴하고 테이블 스캔을 중지합니다.
반면에 IN 연산자가 하위 쿼리와 결합되면 MySQL은 먼저 하위 쿼리를 처리 한 다음 하위 쿼리의 결과를 사용하여 전체 쿼리를 처리해야합니다.
일반적으로 하위 쿼리에 많은 양의 데이터가 포함 된 경우 EXISTS 연산자는 더 나은 성능을 제공합니다.
그러나 서브 쿼리에서 리턴 된 결과 세트가 매우 작은 경우 IN 연산자를 사용하는 쿼리가 더 빠르게 수행됩니다.
우리가 NULL 값을 다루지 않는 한 둘 다 동일해야한다는 것을 이해합니다.
쿼리가 = NULL 값을 반환하지 않는 것과 같은 이유는 NULL입니다. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
부울 대 비교기 인수에 관해서는 부울을 생성하려면 두 값을 비교해야하며 그것이 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에서는 매우 그렇습니다). 대신 이런 식으로 조인 연산자를 사용합니다 : should-i-use-the-keyword-exists-in-sql
기존보다 IN보다 성능이 빠릅니다. 대부분의 필터 기준이 하위 쿼리에 있으면 IN을 사용하는 것이 좋으며 대부분의 필터 기준이 기본 쿼리에 있으면 EXISTS를 사용하는 것이 좋습니다.
IN 연산자를 사용하는 경우 SQL 엔진은 내부 쿼리에서 가져온 모든 레코드를 스캔합니다. 반면에 EXISTS를 사용하는 경우 SQL 엔진은 일치하는 것을 발견하자마자 스캔 프로세스를 중지합니다.
IN
및 EXISTS
등가물 서로 변환 될 수있다.
JOIN
아니라의 대체품으로 사용할 수있는 부분 입니다IN
.