Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

MySQL에서 AND 조건으로 두 개 이상의 조건을 모두 만족하는 레코드 조회하기 — SELF JOIN 활용법

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)

결과 분석

결과를 보면 CarolSam만 조회되었습니다. 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 방식 중 더 적합한 것을 선택해 사용하시면 됩니다.