MySQL에서 하나의 테이블 안에서 두 개 이상의 조건을 동시에 만족하는 레코드를 찾아야 할 때가 있습니다. 예를 들어 '사과와 바나나를 모두 좋아하는 사람'을 찾는 경우처럼, 같은 컬럼의 서로 다른 값이 한 사람(그룹)에 모두 존재하는지 확인해야 하는 상황입니다.
이런 경우 단순한 WHERE 절만으로는 해결하기 어렵고, SELF JOIN(같은 테이블을 자기 자신과 조인)과 AND 연산자를 함께 사용하면 깔끔하게 처리할 수 있습니다. 지금부터 실제 예제를 통해 단계별로 살펴보겠습니다.
1. 데모 테이블 생성하기
먼저 실습에 사용할 데모 테이블을 생성합니다. 사람 이름과 그 사람이 좋아하는 과일을 저장하는 간단한 구조입니다.
mysql> create table selectPerson
-> (
-> PersonId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> PersonName varchar(20),
-> PersonFavouriteFruit varchar(60)
-> );
Query OK, 0 rows affected (0.58 sec)2. 샘플 데이터 삽입하기
INSERT 명령을 사용해 테이블에 레코드를 추가합니다. John, Carol, Sam 세 명의 사람이 각각 여러 개의 좋아하는 과일을 가지도록 데이터를 구성했습니다.
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('John','Banana');
Query OK, 1 row affected (0.14 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('John','Blackberry');
Query OK, 1 row affected (0.12 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('John','Blueberry');
Query OK, 1 row affected (0.12 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Carol','Apple');
Query OK, 1 row affected (0.19 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Carol','Avocado');
Query OK, 1 row affected (0.17 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Carol','Banana');
Query OK, 1 row affected (0.20 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Sam','Ackee');
Query OK, 1 row affected (0.15 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Sam','Apple');
Query OK, 1 row affected (0.89 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Sam','Apricots');
Query OK, 1 row affected (0.12 sec)
mysql> insert into selectPerson(PersonName,PersonFavouriteFruit) values('Sam','Banana');
Query OK, 1 row affected (0.27 sec)3. 전체 레코드 확인하기
SELECT 문을 사용해 테이블의 모든 레코드를 조회합니다.
mysql> select *from selectPerson;
실행 결과는 다음과 같습니다.
+----------+------------+----------------------+ | PersonId | PersonName | PersonFavouriteFruit | +----------+------------+----------------------+ | 1 | John | Banana | | 2 | John | Blackberry | | 3 | John | Blueberry | | 4 | Carol | Apple | | 5 | Carol | Avocado | | 6 | Carol | Banana | | 7 | Sam | Ackee | | 8 | Sam | Apple | | 9 | Sam | Apricots | | 10 | Sam | Banana | +----------+------------+----------------------+ 10 rows in set (0.00 sec)
4. SELF JOIN과 AND로 두 조건을 모두 만족하는 사람 찾기
이제 핵심 질의입니다. '사과(Apple)'와 '바나나(Banana)'를 모두 좋아하는 사람을 찾으려면, 같은 테이블을 두 개의 별칭(tbl1, tbl2)으로 조인한 뒤 각 별칭마다 서로 다른 과일 조건을 WHERE 절에 걸어주면 됩니다.
mysql> SELECT tbl1.PersonName -> FROM selectPerson tbl1 JOIN selectPerson tbl2 on tbl1.PersonName =tbl2.PersonName -> WHERE -> tbl1.PersonFavouriteFruit='Banana' -> and -> tbl2.PersonFavouriteFruit='Apple';
쿼리의 동작 원리를 살펴보면 다음과 같습니다.
- tbl1: '바나나'를 좋아하는 행만 필터링합니다.
- tbl2: '사과'를 좋아하는 행만 필터링합니다.
- JOIN 조건: 두 별칭의 PersonName이 같은 경우에만 매칭하므로, 결국 두 과일을 모두 좋아하는 사람만 남게 됩니다.
실행 결과는 다음과 같습니다.
+------------+ | PersonName | +------------+ | Carol | | Sam | +------------+ 2 rows in set (0.00 sec)
결과 분석
결과를 보면 Carol과 Sam만 조회되었습니다. Carol은 사과·아보카도·바나나를, Sam은 아키·사과·살구·바나나를 좋아하므로 두 조건을 모두 충족합니다. 반면 John은 바나나는 좋아하지만 사과를 좋아하지 않기 때문에 결과에서 제외된 것입니다.
참고: IN 절을 활용한 대안 방법
조건이 많아지면 JOIN 방식 외에 GROUP BY와 HAVING을 사용하는 방법도 있습니다.
mysql> SELECT PersonName
-> FROM selectPerson
-> WHERE PersonFavouriteFruit IN ('Apple', 'Banana')
-> GROUP BY PersonName
-> HAVING COUNT(DISTINCT PersonFavouriteFruit) = 2;이 방식은 조건이 늘어나더라도 IN 목록과 HAVING의 개수만 수정하면 되므로 확장성이 좋다는 장점이 있습니다. 상황에 따라 SELF JOIN 방식과 GROUP BY 방식 중 더 적합한 것을 선택해 사용하시면 됩니다.