종종 필터링 기준이 동적으로 결정되는 쿼리를 작성해야 합니다. 값 목록이 사용자 인터페이스에 의해 지정되고 누락된 값(NULL)도 결과에 포함되거나 제외될 수 있어야 합니다. 이러한 쿼리는 대량의 데이터에서 빠르게 실행되어야 하고 SQL 의미론적으로 올바르며 작동해야 합니다.
IN, NOT IN 조건 및 NULL을 체크하는 조건을 부적절하게 조합하면 예기치 않은 결과가 발생할 수 있습니다. SQL에서 표현식 "NULL IN (...)"은 항상 UNKNOWN을 반환하고, "NOT IN"은 목록의 요소 중 하나라도 NULL인 경우 빈 결과를 초래할 수 있습니다. 잘못 작성된 조건에서 대규모 데이터의 성능이 급격히 떨어질 수 있습니다.
올바른 조합은 다음과 같습니다:
SELECT * FROM sales WHERE region IN ('Moscow','Samara') OR region IS NULL;
SELECT * FROM sales WHERE (region NOT IN ('Moscow','Samara') OR region IS NULL);
SELECT * FROM sales WHERE region NOT IN ('Moscow','Samara') AND region IS NOT NULL;
주요 특징:
"WHERE field NOT IN ('a', NULL)"를 체크하면 무엇이 발생하나요?
결과는 항상 비어 있습니다. 각 행이 목록의 NULL과 비교되므로 UNKNOWN이 발생하고 모든 것이 필터링됩니다.
코드 예:
SELECT * FROM test WHERE name NOT IN ('Ivan', NULL);
"IN (NULL,...)"가 NULL이 있는 행에 값을 제공하나요?
아니요. NULL IN (...) 표현식은 항상 UNKNOWN을 반환하며 TRUE가 아닙니다.
대규모 값 목록에 대한 필터링 속도를 높이는 방법은?
인덱스를 사용하고 목록이 크면(수백/수천 값) 임시 테이블과 JOIN을 사용하는 것이 바람직합니다. 이는 긴 IN보다 필터링 속도를 높입니다.
분석 보고서에서 "WHERE city NOT IN ('London', field_2, NULL)"를 적용했습니다. 그 결과 — 완전히 비어 있는 결과, 아무도 잃어버린 행의 원인을 오랫동안 이해하지 못했습니다.
장점:
단점:
CRM에서 고객 지역 목록을 선택하고 "누락된 값을 포함" 버튼을 추가했습니다. 필터의 논리:
... WHERE city IN ('SPB','NNov') OR city IS NULL
장점:
단점: