PostgreSQL 'NOT IN'및 하위 쿼리


89

이 쿼리를 실행하려고합니다.

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (select consols.mac from consols)

하지만 결과가 없습니다. 나는 그것을 테스트했고 구문에 문제가 있음을 알고 있습니다. MySQL에서는 이러한 쿼리가 완벽하게 작동합니다. 테이블에 mac존재하지 않는 행이 있는지 확인하기 위해 행을 추가 consols했지만 여전히 결과를 제공하지 않습니다.


4
는 IS consols.macNULL이나는 NOT NULL?
Mark Byers 2011

답변:


166

NOT IN을 사용할 때 값이 NULL이 아닌지 확인해야합니다.

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (
    SELECT mac
    FROM consols
    WHERE mac IS NOT NULL -- add this
)

4
참고 : 항상 NULL (및 중복)을 제거하기 WHERE mac IS NOT NULL때문에 하위 쿼리 의 절이 필요하지 않습니다 In(...). 집합은 NULL을 포함 할 수 없기 때문에
wildplasser

7
@wildplasser 나는 그것에 대해 모른다. 내가 추가 할 때까지 나를 위해 작동하지 않았습니다 IS NOT NULL. 중첩 SELECT은 몇 개를 반환하고 NULLS있었고 IN(SELECT...).
robins35 2017

2
왜 이것이 IS NOT NULL작동 하는지에 대한 설명에 크게 감사드립니다 .
mbarkhau

7
비교 가 참이 아니거나 거짓이 아니기 때문에 절 NULL에서 사용 이 NOT IN작동하지 않는 것 같습니다 NULL. sqlbadpractices.com/using-not-in-operator-with-null-values
mbarkhau

2
is not null하위 쿼리가 일치하는 값과 하나 이상의 값을 생성하지 않는 경우 쿼리는 행을 반환하지 않습니다 null. 가입일 섹션 9.22 "[...] 필적 우측 값 및 상기 적어도 하나의 우측 행 수율 널은 NOT 구조 될 것이다 널 결과가 존재하지 않는 경우는 사실이 아니다 : 전류 (버전 10)의 PostgreSQL 매뉴얼 . "
Christopher Lewis

29

NOT IN을 사용할 때는 null 케이스를 자동으로 처리하는 NOT EXISTS도 고려해야합니다. PostgreSQL Wiki 참조

SELECT mac, creation_date 
FROM logs lo
WHERE logs_type_id=11
AND NOT EXISTS (
  SELECT *
  FROM consols nx
  WHERE nx.mac = lo.mac
  );

3
사용하는 경우 또한 큰 성능 손실을주의 NOT EXISTS... NOT IN
IcanDivideBy0

1
@ IcanDivideBy0 대부분의 경우 동일한 쿼리 계획을 생성합니다. 테스트 해 보셨나요?
wildplasser

1
하위 쿼리의 경우 NOT EXISTS 대신 NOT IN을 사용하면 성능이 향상됩니다. 참조 wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_NOT_IN
Gerbrand

8

LEFT JOIN 및 IS NULL 조건을 사용할 수도 있습니다.

SELECT 
  mac, 
  creation_date 
FROM 
  logs
    LEFT JOIN consols ON logs.mac = consols.mac
WHERE 
  logs_type_id=11
AND
  consols.mac IS NULL;

"mac"열의 인덱스는 성능을 향상시킬 수 있습니다.

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