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

LEFT JOIN을 활용해 MySQL 테이블의 중복 데이터 제거하기

MySQL에서 동일한 값이 여러 번 저장된 중복 레코드는 데이터의 신뢰성을 떨어뜨리고 저장 공간을 낭비합니다. 이 글에서는 LEFT JOINGROUP BY, MIN() 함수를 조합하여 중복 값을 손쉽게 제거하는 방법을 실제 예제와 함께 단계별로 살펴보겠습니다.

1. 테이블 생성

먼저 실습에 사용할 테이블을 생성합니다.

mysql> create table DemoTable
(
    Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    FirstName varchar(100)
);
Query OK, 0 rows affected (0.46 sec)

Id 컬럼은 AUTO_INCREMENT로 설정되어 각 레코드가 고유한 번호를 가지며, FirstName 컬럼에는 이름이 저장됩니다.

2. 샘플 데이터 삽입

INSERT 문을 사용하여 의도적으로 중복된 이름을 포함한 레코드를 입력합니다.

mysql> insert into DemoTable(FirstName) values('Chris');
Query OK, 1 row affected (0.18 sec)
mysql> insert into DemoTable(FirstName) values('Robert');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable(FirstName) values('Robert');
Query OK, 1 row affected (0.07 sec)
mysql> insert into DemoTable(FirstName) values('John');
Query OK, 1 row affected (0.14 sec)
mysql> insert into DemoTable(FirstName) values('John');
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable(FirstName) values('Mike');
Query OK, 1 row affected (0.09 sec)

3. 현재 데이터 확인

SELECT 문으로 전체 레코드를 조회하면 다음과 같습니다.

mysql> select *from DemoTable;

실행 결과:

+----+-----------+
| Id | FirstName |
+----+-----------+
|  1 | Chris     |
|  2 | Robert    |
|  3 | Robert    |
|  4 | John      |
|  5 | John      |
|  6 | Mike      |
+----+-----------+
6 rows in set (0.00 sec)

'Robert'와 'John'이 각각 두 번씩 저장되어 있어 총 6개의 레코드가 존재합니다.

4. LEFT JOIN으로 중복 제거하기

다음은 중복 값을 제거하는 핵심 쿼리입니다.

mysql> delete tbl from DemoTable tbl
left join(
    select min(Id) as Id, FirstName
    from DemoTable
    group by FirstName
) tbl1 ON tbl.Id = tbl1.Id AND tbl.FirstName = tbl1.FirstName
where tbl1.Id IS NULL;
Query OK, 2 rows affected (0.16 sec)

쿼리 동작 원리

이 쿼리의 작동 방식은 다음과 같습니다.

① 서브쿼리: FirstName 기준으로 GROUP BY를 수행하고, 각 그룹에서 MIN(Id), 즉 가장 작은 Id를 선택합니다. 이렇게 하면 각 이름별로 '대표 레코드' 한 개만 남게 됩니다.

② LEFT JOIN: 원본 테이블(tbl)을 서브쿼리 결과(tbl1)와 Id 및 FirstName 기준으로 LEFT JOIN합니다. 대표 레코드는 매칭되지만, 나머지 중복 레코드는 매칭되지 않아 tbl1.Id가 NULL이 됩니다.

③ DELETE: WHERE 절에서 tbl1.Id IS NULL인 행, 즉 그룹 내 최소 Id가 아닌 중복 레코드만 삭제합니다.

5. 삭제 후 결과 확인

다시 한번 테이블을 조회해 보겠습니다.

mysql> select *from DemoTable;

실행 결과:

+----+-----------+
| Id | FirstName |
+----+-----------+
|  1 | Chris     |
|  2 | Robert    |
|  4 | John      |
|  6 | Mike      |
+----+-----------+
4 rows in set (0.00 sec)

중복된 'Robert'(Id 3)와 'John'(Id 5)이 삭제되고, 각 이름당 가장 작은 Id를 가진 레코드만 남아 총 4개의 레코드가 조회됩니다.

마무리

이처럼 LEFT JOIN과 GROUP BY, MIN() 함수를 활용하면 별도의 임시 테이블 없이 하나의 DELETE 문으로 중복 데이터를 깔끔하게 정리할 수 있습니다. 참고로 MySQL 8.0 이상에서는 윈도우 함수인 ROW_NUMBER()를 사용하는 방법도 있으니, 상황에 맞게 선택하여 활용하시기 바랍니다.