NOT EXISTS와 NOT IN과 LEFT JOIN의 차이점은 무엇입니까?


151

NOT EXISTS, NOT IN 또는 LEFT JOIN WHERE가 NULL 인 경우 SQL 쿼리에서 동일한 작업을 수행 할 수 있습니다. 예를 들면 다음과 같습니다.

SELECT a FROM table1 WHERE a NOT IN (SELECT a FROM table2)

SELECT a FROM table1 WHERE NOT EXISTS (SELECT * FROM table2 WHERE table1.a = table2.a)

SELECT a FROM table1 LEFT JOIN table2 ON table1.a = table2.a WHERE table1.a IS NULL

모든 구문이 올바른지 확실하지 않지만 이것이 내가 본 일반적인 기술입니다. 왜 다른 것을 사용하기로합니까? 성능이 다른가요? 이 중 가장 빠르거나 가장 효율적인 것은 무엇입니까? (구현에 따라 달라지면 언제 사용합니까?)


6
많은 일반적인 SQL 엔진은 실행 계획을 볼 수있는 기능을 제공합니다. 이런 식으로 논리적으로 동등한 쿼리에 대해 효율성에서 상당한 차이를 발견 할 수 있습니다. 모든 방법의 성공 여부는 테이블 크기, 존재하는 인덱스 등의 요소에 따라 다릅니다.
Chris Farmer

2
@wich : EXISTS절에서 정확히 리턴하는 것을 데이터베이스가 신경 쓰지 않습니다 . *, NULL또는 무엇이든 반환 할 수 있습니다.이 모든 것이 최적화됩니다.
Quassnoi

2
@wich-왜? 둘 다 여기에 : techonthenet.com/sql/exists.php 와 여기에 : msdn.microsoft.com/en-us/library/ms188336.aspx *를 사용하는 것 같습니다 ...
froadie

8
@wich : 이것은 "관심 표현"에 관한 것이 아닙니다. 이것은 쿼리 파서가 SELECT와 사이에 무언가를 넣도록 요구하는 것에 관한 것 FROM입니다. 그리고 *입력하기가 더 쉽습니다. 예, SQL자연어와 비슷하지만 프로그래밍 된 기계 인 기계에 의해 구문 분석되고 실행됩니다. 그것은 갑자기 당신의 큐비클에 침입하여 " EXISTS파싱 ​​후 파기하는 것에 질려서 쿼리 에서 여분의 필드를 요구하지 말라!"고 외치는 것이 아닙니다 . 컴퓨터로도 괜찮습니다.
Quassnoi

1
@Quassnoi 당신이 코드를 해석하는 기계의 목적으로 만 코드를 작성했다면 코드는 끔찍해 보일 것입니다. 불행히도 아주 소수의 사람들이 그렇게 작동합니다. 그러나 다른 광학 장치에서 코드를 작성하고 기계가 동료와의 통신으로 수행하려는 작업을 표현하는 코드를 작성하면 더 좋고 유지 관리가 쉬운 코드를 작성하게됩니다. 컴퓨터가 아닌 사람들을 위해 똑똑하고 코드를 작성하십시오.
느릅 나무

답변:


139

간단히 말해서 :

NOT IN조금 다릅니다 : NULL목록에 하나만 있는 경우 절대 일치하지 않습니다 .

  • 에서 MySQL, NOT EXISTS조금 덜 효율적이다

  • 에서가 SQL Server, LEFT JOIN / IS NULL덜 효율적이다

  • 에서가 PostgreSQL, NOT IN덜 효율적이다

  • 에서 Oracle세 가지 방법은 모두 동일합니다.


1
링크 주셔서 감사합니다! 빠른 개요에 감사드립니다 ... 내 사무실이 어떤 이유로 링크를 차단하고 있습니다 : P 그러나 일반 컴퓨터에 도착하자마자 확인하겠습니다.
froadie

2
또 다른 요점은 쿼리가 table1 .a포함 NULLEXISTS경우이 행을 반환하지 않지만 NOT IN쿼리 table2는 비어있는 경우 입니다. NOT 대에없는이 Null 허용 열 EXISTS : SQL 서버
마틴 스미스

@MartinSmith : 다음 NULL NOT IN ()과 같이 true로 평가 (not NULL)NOT EXISTS (NULL = column)
Quassnoi

2
@Quassnoi-어, 좋은 지적은 잘못된 길을 찾았습니다. 는 NOT EXISTS항상 행을 리턴하지만 NOT IN하위 쿼리에 행을 반환하지 않는 경우에만 그렇게 할 것입니다.
Martin Smith

5

데이터베이스가 쿼리를 최적화하는 데 능숙하면 두 번째는 세 번째에 가까운 것으로 변환됩니다.

질문에있는 것과 같은 간단한 상황의 경우 모두 조인으로 실행되므로 차이가 거의 없거나 전혀 없어야합니다. 보다 복잡한 쿼리에서는 데이터베이스가 not innot exists쿼리를 조인하지 못할 수 있습니다 . 이 경우 쿼리 속도가 훨씬 느려집니다. 반면, 사용할 수있는 인덱스가없는 경우에도 조인이 제대로 수행되지 않을 수 있으므로 조인을 사용한다고해서 안전하다는 의미는 아닙니다. 성능 문제가 있는지 확인하려면 쿼리의 실행 계획을 조사해야합니다.


2

널을 피한다고 가정하면 표준 SQL을 사용하여 결합 방지 를 작성하는 모든 방법입니다 .

명백한 생략은 다음을 사용하는 것과 같습니다 EXCEPT.

SELECT a FROM table1
EXCEPT
SELECT a FROM table2

Oracle에서는 MINUS연산자 를 사용해야합니다 (아마도 더 나은 이름).

SELECT a FROM table1
MINUS
SELECT a FROM table2

독점적 인 구문에 관해서는 OUTER APPLYSQL Server에서 사용하는 제품에 따라 조사 할 가치가있는 비표준 등가물이있을 수도 있습니다 ( 예 :

SELECT t1.a
  FROM table1 t1
       OUTER APPLY 
       (
        SELECT t2.a
          FROM table2 t2
         WHERE t2.a = t1.a
       ) AS dt1
 WHERE dt1.a IS NULL;

0

다중 필드 기본 키를 사용하여 테이블에 데이터를 삽입해야하는 경우 Access에서 시도했지만 모든 데이터베이스에서는 "테이블에 '이러한'값이있는 레코드가 없는지"확인하지 않는 것이 훨씬 빠릅니다. -오히려 테이블에 삽입하면 초과 키 (키로)가 두 번 삽입되지 않습니다.


0

NOT IN, NOT EXISTS 등과 같은 역 키워드는 항상 성능 관점에서 사용하지 마십시오. 역 항목을 확인하려면 DBMS가 사용 가능한 모든 항목을 통해 실행하고 역 선택을 삭제해야합니다.


1
그리고 실제로 필요할 때 해결 방법으로 무엇을 제안 NOT합니까?
dnoeth

원인의 선택권이 없을 때는 NOT 연산을 사용해야하며 이것이 존재하는 이유입니다. 모범 사례는 다른 대안 솔루션이있을 때이를 피하는 것입니다.
Lahiru Cooray 2016

@onedaywhen, 옵티마이 저가 쿼리를 변환하고 잘못된 결과
David דודו Markovitz

@DuduMarkovitz : 예. SQL Server 팀에 연락하여 버그를 인정하지만 쿼리를 느리게 할 수 있기 때문에 버그를 수정하지 않으면 처리해야 할 버그 입니다 .
언젠가

@onedaywhen-이것은 내가 가정 한 가상의 시나리오가 아니었다 :-) 우연히 버그 세부 사항을 기억 하는가?
David דודו Markovitz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.