개요
MySQL에서 NOT IN 연산자와 서브쿼리를 활용하면, 특정 값만 반복해서 가진 레코드만 골라내는 조건부 GROUP BY 로직을 손쉽게 구현할 수 있습니다. 이번 글에서는 예제 테이블을 생성하고, NOT IN()을 사용해 원하는 결과를 추출하는 과정을 단계별로 살펴보겠습니다.
1단계: 테이블 생성
먼저 데모용 테이블을 생성합니다.
mysql> create table DemoTable
(
Name varchar(40),
Score int
);
Query OK, 0 rows affected (0.48 sec)2단계: 레코드 삽입
INSERT 명령을 사용해 테이블에 샘플 데이터를 입력합니다.
mysql> insert into DemoTable values('Adam',89);
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable values('Adam',89);
Query OK, 1 row affected (0.14 sec)
mysql> insert into DemoTable values('Chris',89);
Query OK, 1 row affected (0.13 sec)
mysql> insert into DemoTable values('Chris',89);
Query OK, 1 row affected (0.14 sec)
mysql> insert into DemoTable values('Bob',98);
Query OK, 1 row affected (0.10 sec)
mysql> insert into DemoTable values('Bob',89);
Query OK, 1 row affected (0.16 sec)3단계: 전체 데이터 확인
SELECT 문으로 테이블의 모든 레코드를 조회합니다.
mysql> select *from DemoTable;
실행 결과는 다음과 같습니다.
+-------+-------+ | Name | Score | +-------+-------+ | Adam | 89 | | Adam | 89 | | Chris | 89 | | Chris | 89 | | Bob | 98 | | Bob | 89 | +-------+-------+ 6 rows in set (0.00 sec)
4단계: NOT IN()을 활용한 조건부 GROUP BY 쿼리 실행
아래 쿼리는 NOT IN() 서브쿼리를 사용하여, 점수가 89가 아닌 레코드를 하나라도 가진 이름은 제외하고 오직 89점만 기록한 이름들만 중복 없이 조회합니다.
mysql> select distinct Name from DemoTable where Name not in(select Name from DemoTable where Score <> 89);
결과는 다음과 같습니다.
+-------+ | Name | +-------+ | Adam | | Chris | +-------+ 2 rows in set (0.06 sec)
쿼리 동작 원리
서브쿼리 select Name from DemoTable where Score <> 89는 점수가 89가 아닌 레코드의 이름 목록을 반환합니다. 위 예제에서는 98점을 받은 Bob이 여기에 해당하므로, 메인 쿼리의 NOT IN 조건에 의해 Bob은 최종 결과에서 제외됩니다. 반면 Adam과 Chris는 보유한 모든 레코드의 점수가 89이므로 결과에 포함되며, DISTINCT 키워드 덕분에 각각 한 번씩만 출력됩니다.
이처럼 NOT IN과 서브쿼리를 조합하면 별도의 복잡한 JOIN이나 HAVING 절 없이도, "특정 조건을 만족하지 않는 그룹 전체를 걸러내는" 필터링 로직을 간결하게 작성할 수 있습니다.