데이터베이스를 운영하다 보면 동일한 값이 여러 번 저장되어 있는 경우가 많습니다. 이럴 때 GROUP BY 절과 MIN() 함수를 함께 사용하면 중복된 값 중에서 하나만 선택하여 조회할 수 있습니다.
기본 문법
중복된 값을 건너뛰고 각 그룹에서 하나의 행만 가져오는 기본적인 쿼리 구문은 다음과 같습니다.
SELECT MIN(yourColumnName1), yourColumnName2 FROM yourTableName GROUP BY yourColumnName2;
여기서 MIN() 함수는 그룹별로 가장 작은 값을 반환하며, GROUP BY는 지정한 컬럼을 기준으로 행들을 묶어줍니다. 두 기능을 조합하면 중복된 이름별로 고유 ID가 가장 작은 한 개의 레코드만 결과로 남게 됩니다.
예제 테이블 생성하기
실제 동작을 확인하기 위해 먼저 테스트용 테이블을 만들어 보겠습니다.
mysql> CREATE TABLE doNotSelectDuplicateValuesDemo
-> (
-> User_Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> User_Name varchar(20)
-> );
Query OK, 0 rows affected (0.78 sec)샘플 데이터 삽입하기
이제 INSERT 명령으로 의도적으로 중복된 이름을 포함한 레코드를 여러 개 입력합니다.
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('John');
Query OK, 1 row affected (0.15 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Carol');
Query OK, 1 row affected (0.09 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Carol');
Query OK, 1 row affected (0.17 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Carol');
Query OK, 1 row affected (0.08 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Sam');
Query OK, 1 row affected (0.28 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Mike');
Query OK, 1 row affected (0.19 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Bob');
Query OK, 1 row affected (0.16 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('David');
Query OK, 1 row affected (0.21 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Maxwell');
Query OK, 1 row affected (0.13 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Bob');
Query OK, 1 row affected (0.11 sec)
mysql> INSERT INTO doNotSelectDuplicateValuesDemo(User_Name) VALUES('Ramit');
Query OK, 1 row affected (0.16 sec)전체 레코드 확인하기
SELECT 문으로 테이블에 저장된 모든 데이터를 조회해 보겠습니다.
mysql> SELECT * FROM doNotSelectDuplicateValuesDemo;
실행 결과는 다음과 같습니다. 'Carol'은 3번, 'Bob'은 2번 저장되어 있음을 확인할 수 있습니다.
+---------+-----------+ | User_Id | User_Name | +---------+-----------+ | 1 | John | | 2 | Carol | | 3 | Carol | | 4 | Carol | | 5 | Sam | | 6 | Mike | | 7 | Bob | | 8 | David | | 9 | Maxwell | | 10 | Bob | | 11 | Ramit | +---------+-----------+ 11 rows in set (0.00 sec)
중복 제거 쿼리 실행하기
이제 GROUP BY와 MIN()을 활용해 중복된 이름당 하나의 레코드만 선택하는 쿼리를 실행합니다.
mysql> SELECT MIN(User_Id), User_Name FROM doNotSelectDuplicateValuesDemo GROUP BY User_Name;
실행 결과는 다음과 같습니다.
+--------------+-----------+ | min(User_Id) | User_Name | +--------------+-----------+ | 1 | John | | 2 | Carol | | 5 | Sam | | 6 | Mike | | 7 | Bob | | 8 | David | | 9 | Maxwell | | 11 | Ramit | +--------------+-----------+ 8 rows in set (0.07 sec)
결과 분석
원래 11개의 행이 있었지만, 쿼리 실행 후에는 8개의 행만 반환되었습니다. 'Carol'은 세 개의 레코드(2, 3, 4번) 중 가장 작은 ID인 2번만, 'Bob'은 두 개의 레코드(7, 10번) 중 7번만 선택된 것을 볼 수 있습니다.
이처럼 GROUP BY와 집계 함수를 조합하면 별도의 DISTINCT나 서브쿼리 없이도 간단하게 중복 데이터를 정리할 수 있습니다. 참고로 가장 큰 값을 기준으로 선택하고 싶다면 MIN() 대신 MAX() 함수를 사용하면 됩니다.