VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
EXISTS는 예 또는 아니오의 질문을 합니다: 이 서브쿼리가 무언가를 찾았는가. 서브쿼리가 무엇을 반환했는지는 상관하지 않고 행이 있었는지만 보므로, 관련된 행이 있는지 검사하되 그 열은 하나도 필요 없을 때 알맞은 도구입니다.
시작하기 전에 mysql -u root -p sakila로 클라이언트를 여세요.
EXISTS의 동작 방식
COLUMN_LIST를 원하는 열로, TABLE_NAME과 OTHER_TABLE을 2개의 테이블로, OUTER_ALIAS와 INNER_ALIAS를 그 이름으로, COLUMN_NAME을 둘을 연결하는 열로, 안쪽의 WHERE를 행을 관련되게 만드는 조건으로 바꾸세요.
SELECT 1은 관례입니다. select 목록은 무시되므로 SELECT 1, SELECT *, SELECT column은 똑같이 동작하고, 1은 아무것도 읽지 않는다는 것을 분명하게 말해 줍니다.
이 서브쿼리는 상관 서브쿼리입니다: 바깥 행을 참조합니다. 서버는 첫 번째로 일치하는 행에서 멈출 수 있는데, 예라고 답하기에는 1개면 충분하기 때문입니다.
예제
- 일치하는 것이 있는 행
- 일치하는 것이 없는 행
NOT EXISTS가 나머지 부분이고, 안티 조인을 쓰는 방법입니다.
WHERE f.film_id IS NULL로 답하고, 2가지 형태는 같은 행을 반환합니다.
NOT IN이 안전하지 않은 곳에서 NOT EXISTS는 안전합니다
IN 레슨은 목록에 NULL이 들어 있을 때NOT IN이 행을 하나도 반환하지 않는 모습을 보여 줍니다. NOT EXISTS에는 그런 함정이 없는데, 값을 비교하지 않기 때문입니다: 행을 셉니다.
그러므로 서브쿼리가 NULL일 수 있는 열을 읽을 때는 NOT EXISTS를 쓰세요. NOT IN은 NOT NULL로 선언된 열에서는 괜찮고, 그것이 더 이상 성립하지 않는 순간 위험 요소가 됩니다.
EXISTS는 행을 절대 늘리지 않습니다
일치하는 행이 여러 개인 테이블로의 조인은 바깥 행을 일치마다 한 번씩 반복하며, INNER JOIN 레슨이 그것을 보여 줍니다.EXISTS는 그렇게 할 수 없습니다: 예 또는 아니오로 답하므로, 일치가 몇 개이든 각 바깥 행은 한 번만 나타납니다.
EXISTS, IN, 조인은 모두 “관련된 행이 있다”를 표현할 수 있고, 어느 것이 가장 빠른지는 데이터에 따라 다릅니다. MySQL의 서브쿼리 대 JOIN이 플랜과 함께 그것들을 비교합니다.
요약
- 서브쿼리가 행을 하나라도 찾는지 검사하려면
EXISTS를 사용하세요. - select 목록은 무시되므로, 안에는
SELECT 1을 쓰세요. - 일치하는 것이 없는 행에는
NOT EXISTS를 사용하세요. - 서브쿼리 열이 NULL일 수 있으면
NOT IN보다NOT EXISTS를 쓰세요. - 조인이라면 일으켰을 행의 증가가 없다고 예상하세요.
함께 보기
- 상관 서브쿼리 — EXISTS가 사용하는 서브쿼리 형태
- IN — NULL 함정이 있는 연산자
- LEFT JOIN — 조인으로 묻는 같은 질문
- MySQL의 서브쿼리 대 JOIN — 옵티마이저가 선호하는 형태