예외 연산자 대 NOT IN


답변:


29

EXCEPT와 사이에는 두 가지 주요 차이점이 있습니다 NOT IN.

EXCEPTDISTINCT오른쪽 테이블에 나타나지 않는 왼쪽 테이블 의 값을 필터링 합니다. NOT EXISTSwith DISTINCT절 을 수행하는 것과 본질적으로 동일 합니다.

또한 두 테이블 (또는 테이블의 열 하위 집합)이 쿼리의 왼쪽과 오른쪽에 동일한 수의 열을 가질 것으로 예상합니다.

예를 들어 다음을 수행 할 수 없습니다.

SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB

이로 인해 오류가 발생합니다.

UNION, INTERSECT 또는 EXCEPT 연산자를 사용하여 결합 된 모든 쿼리는 대상 목록에 동일한 수의 표현식이 있어야합니다.

NOT INDISTINCT값을 필터링하지 않고 왼쪽 테이블에서 오른쪽 테이블에 나타나지 않는 모든 값을 반환합니다.

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을 필터링하고 #ExistingCustomers8을 복제합니다.

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


필요한 경우를 제외하고 인덱스를 사용합니까?
JohnOpincar

1

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_namelast_name직원 모든 사람들뿐만 아니라, 관리자가 없습니다.

* : 그러나 구성은 아직 SQL Server에서 구현되지 않았습니다.


-2

기본 조회의 술어와 부속 조회 사이에 상관이 있어야하기 때문에 위의 NOT IN이 실패합니다. 제외하면 UNCORRELATED 하위 쿼리가 나타납니다.

SELECT * FROM TableA AS nc WHERE ID IN IN (SELECT ID, Table FROM AS AS ec 여기서 nc.ID = ec.ID)

EXCEPT가 더 좋으며 IS NULL / IS NOT NULL 술어를 사용하지 않고 널 행을 처리합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.