답변:
EXCEPT
와 사이에는 두 가지 주요 차이점이 있습니다 NOT IN
.
EXCEPT
DISTINCT
오른쪽 테이블에 나타나지 않는 왼쪽 테이블 의 값을 필터링 합니다. NOT EXISTS
with DISTINCT
절 을 수행하는 것과 본질적으로 동일 합니다.
또한 두 테이블 (또는 테이블의 열 하위 집합)이 쿼리의 왼쪽과 오른쪽에 동일한 수의 열을 가질 것으로 예상합니다.
예를 들어 다음을 수행 할 수 없습니다.
SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB
이로 인해 오류가 발생합니다.
UNION, INTERSECT 또는 EXCEPT 연산자를 사용하여 결합 된 모든 쿼리는 대상 목록에 동일한 수의 표현식이 있어야합니다.
NOT IN
DISTINCT
값을 필터링하지 않고 왼쪽 테이블에서 오른쪽 테이블에 나타나지 않는 모든 값을 반환합니다.
NOT IN
한 테이블의 단일 열을 다른 테이블 또는 하위 쿼리의 단일 열과 비교해야합니다.
예를 들어 하위 쿼리가 여러 열을 반환하는 경우 :
SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)
다음과 같은 오류가 발생합니다.
EXISTS에 부속 조회가 도입되지 않은 경우 선택 목록에 하나의 표현식 만 지정할 수 있습니다.
그러나 오른쪽 테이블에 NULL
의해 필터링되는 값에가 포함되어 NOT IN
있으면 빈 결과 집합이 반환되어 예기치 않은 결과가 발생할 수 있습니다.
CREATE TABLE #NewCustomers (ID INT);
CREATE TABLE #ExistingCustomers (ID INT);
INSERT INTO #NewCustomers
( ID )
VALUES
(8), (9), (10), (1), (3), (8);
INSERT INTO #ExistingCustomers
( ID )
VALUES
( 1) , (2), (3), (4), (5);
-- EXCEPT filters for DISTINCT values
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec
-- NOT IN returns all values without filtering
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)
위의 두 쿼리에서 EXCEPT
에서 3 개의 행을 반환 #NewCustomers
하고 일치하는 1과 3을 필터링하고 #ExistingCustomers
8을 복제합니다.
NOT IN
이 구별 필터링을 수행하지 않고 #NewCustomers
중복 8 에서 4 개의 행을 반환합니다 .
이제 테이블 에 a NULL
를 추가하면에 #ExistingCustomers
의해 반환 된 것과 동일한 결과가 표시 EXCEPT
되지만 NOT IN
빈 결과 집합이 반환됩니다.
INSERT INTO #ExistingCustomers
( ID )
VALUES
( NULL );
-- With NULL values in the right-hand table, EXCEPT still returns the same results as above
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec
-- NOT IN now returns no results
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)
DROP TABLE #NewCustomers;
DROP TABLE #ExistingCustomers;
대신 에 Gail Shaw의 블로그에서이 둘을 비교해 NOT IN
보아야 합니다.NOT EXISTS
Mark Sinkinson의 탁월한 의견에 대한 중독 :
NOT IN에서는 한 테이블의 단일 열을 다른 테이블 또는 하위 쿼리의 단일 열과 비교해야합니다.
실제로 NOT IN
둘 이상의 열로 수행 할 수 있습니다 .
예를 들어 이것은 현행으로 유효한 * SQL 쿼리입니다.
SELECT E.first_name, E.last_name
FROM employees E
WHERE (E.first_name, E.last_name) NOT IN
(SELECT M.first_name, M.last_name FROM managers M)
어느 반환 first_name
과 last_name
직원 모든 사람들뿐만 아니라, 관리자가 없습니다.
* : 그러나 구성은 아직 SQL Server에서 구현되지 않았습니다.