셀프 조인(SELF JOIN)은 하나의 테이블이 자기 자신과 조인되는 기법으로, 같은 테이블 내의 행들을 서로 비교하거나 연관 지어야 할 때 유용하게 사용됩니다. 이 글에서는 실제 예제를 통해 MySQL에서 셀프 조인을 사용하는 방법을 단계별로 살펴보겠습니다.
1단계: 테이블 생성하기
먼저 셀프 조인을 실습할 테이블을 만들어 보겠습니다. 아래 쿼리를 실행하여 SelfJoinDemo 테이블을 생성합니다.
mysql> create table SelfJoinDemo
-> (
-> Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> CountryName varchar(20),
-> CountryRank int,
-> `Year` varchar(10)
-> );
Query OK, 0 rows affected (1.02 sec)
테이블은 국가 이름(CountryName), 국가 순위(CountryRank), 연도(Year) 세 개의 컬럼으로 구성되어 있습니다.
2단계: 데이터 삽입하기
다음으로 INSERT 명령어를 사용해 테이블에 샘플 데이터를 입력합니다.
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('US',1,'2016');
Query OK, 1 row affected (0.12 sec)
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('UK',5,'2013');
Query OK, 1 row affected (0.16 sec)
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('France',45,'2010');
Query OK, 1 row affected (0.21 sec)
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('Turkey',3,'2000');
Query OK, 1 row affected (0.17 sec)
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('Japan',78,'1995');
Query OK, 1 row affected (0.21 sec)
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('Romania',110,'2007');
Query OK, 1 row affected (0.22 sec)
mysql> insert into SelfJoinDemo(CountryName,CountryRank,`Year`) values('UK',3,'2000');
Query OK, 1 row affected (0.16 sec)3단계: 전체 데이터 조회하기
SELECT 문을 사용해 테이블에 저장된 모든 레코드를 확인합니다.
mysql> select *from SelfJoinDemo;
실행 결과는 다음과 같습니다.
+----+-------------+-------------+------+
| Id | CountryName | CountryRank | Year |
+----+-------------+-------------+------+
| 1 | US | 1 | 2016 |
| 2 | UK | 5 | 2013 |
| 3 | France | 45 | 2010 |
| 4 | Turkey | 3 | 2000 |
| 5 | Japan | 78 | 1995 |
| 6 | Romania | 110 | 2007 |
| 7 | UK | 3 | 2000 |
+----+-------------+-------------+------+
7 rows in set (0.00 sec)
총 7개의 레코드가 저장되어 있으며, 'UK'는 서로 다른 연도와 순위로 두 번 등록되어 있는 것을 확인할 수 있습니다.
4단계: 셀프 조인 쿼리 실행하기
이제 본격적으로 셀프 조인을 적용해 보겠습니다. 아래 쿼리는 동일한 테이블을 t1과 t2라는 두 개의 별칭(alias)으로 참조하여, 'US'와 같은 연도를 가진 레코드를 찾아냅니다.
mysql> SELECT DISTINCT t1.CountryName, t2.Year
-> FROM SelfJoinDemo AS t1,
-> SelfJoinDemo AS t2
-> WHERE t1.Year=t2.Year
-> and t1.CountryName='US';
실행 결과는 다음과 같습니다.
+-------------+------+
| CountryName | Year |
+-------------+------+
| US | 2016 |
+-------------+------+
1 row in set (0.00 sec)
셀프 조인의 핵심 포인트
위 쿼리에서 주목해야 할 부분은 다음과 같습니다.
첫째, FROM 절에서 동일한 테이블을 두 번 지정하고 각각 t1, t2라는 별칭을 부여했습니다. 이렇게 하면 MySQL은 마치 두 개의 독립적인 테이블처럼 처리합니다.
둘째, WHERE 절의 t1.Year=t2.Year 조건이 두 테이블 참조를 연결하는 조인 조건 역할을 합니다.
셋째, DISTINCT 키워드를 사용해 중복된 결과 행을 제거했습니다. 셀프 조인은 카티션 곱(cartesian product)이 발생하기 쉬우므로, 필요에 따라 중복 제거나 추가 필터링 조건을 넣어주는 것이 좋습니다.
이처럼 셀프 조인은 직원과 관리자 관계, 카테고리 계층 구조, 동일한 속성 값을 가진 행 비교 등 하나의 테이블 내에서 행 간 관계를 분석해야 하는 다양한 상황에서 활용할 수 있는 강력한 기법입니다.