개요
MySQL에서 GROUP BY 절을 사용할 때 각 그룹에서 특정 행을 선택하거나 정렬해야 하는 경우가 자주 발생합니다. 이 글에서는 서브쿼리와 MIN() 함수를 활용하여 그룹별로 원하는 행을 효과적으로 추출하는 방법을 단계별로 살펴보겠습니다.
1. 예제 테이블 생성하기
먼저 실습에 사용할 테이블을 생성합니다.
mysql> create table DemoTable1572
-> (
-> StudentId int,
-> StudentMarks int,
-> StudentName varchar(20)
-> );
Query OK, 0 rows affected (0.56 sec)2. 샘플 데이터 삽입하기
INSERT 명령어를 사용해 테이블에 학생 데이터를 입력합니다.
mysql> insert into DemoTable1572 values(1,79,'Sam'); Query OK, 1 row affected (0.10 sec) mysql> insert into DemoTable1572 values(2,89,'Chris'); Query OK, 1 row affected (0.12 sec) mysql> insert into DemoTable1572 values(3,98,'David'); Query OK, 1 row affected (0.22 sec) mysql> insert into DemoTable1572 values(4,79,'Bob'); Query OK, 1 row affected (0.10 sec)
3. 전체 데이터 조회하기
SELECT 문으로 테이블의 모든 레코드를 확인합니다.
mysql> select * from DemoTable1572;
실행 결과는 다음과 같습니다.
+-----------+--------------+-------------+ | StudentId | StudentMarks | StudentName | +-----------+--------------+-------------+ | 1 | 79 | Sam | | 2 | 89 | Chris | | 3 | 98 | David | | 4 | 79 | Bob | +-----------+--------------+-------------+ 4 rows in set (0.00 sec)
4. GROUP BY로 그룹별 행 선택하기
여기서 핵심은 동일한 점수(StudentMarks)를 가진 학생들 중 가장 작은 StudentId를 가진 행만 선택하는 것입니다. Sam(79점)과 Bob(79점)은 같은 그룹에 속하므로, 이 중 StudentId가 더 작은 Sam만 결과에 포함됩니다.
아래 쿼리는 GROUP BY와 MIN()을 조합한 서브쿼리를 사용하여 이를 구현합니다.
mysql> select * from DemoTable1572
-> where StudentId in (select min(StudentId) from DemoTable1572 group by StudentMarks);실행 결과는 다음과 같습니다.
+-----------+--------------+-------------+ | StudentId | StudentMarks | StudentName | +-----------+--------------+-------------+ | 1 | 79 | Sam | | 2 | 89 | Chris | | 3 | 98 | David | +-----------+--------------+-------------+ 3 rows in set (0.10 sec)
쿼리 동작 원리 설명
이 쿼리가 어떻게 동작하는지 내부적으로 살펴보겠습니다.
- 내부 서브쿼리:
select min(StudentId) from DemoTable1572 group by StudentMarks는 점수별로 학생들을 그룹화한 후, 각 그룹에서 가장 작은 StudentId 값을 반환합니다. 즉, 79점 그룹에서는 1(Sam), 89점 그룹에서는 2(Chris), 98점 그룹에서는 3(David)이 선택됩니다. - 외부 쿼리:
WHERE StudentId IN (...)조건을 통해 해당 ID를 가진 행만 최종 결과로 출력합니다.
참고 사항
만약 각 그룹에서 가장 큰 StudentId를 선택하고 싶다면 MIN() 대신 MAX() 함수를 사용하면 됩니다. 또한 MySQL 8.0 이상에서는 윈도우 함수(Window Function)인 ROW_NUMBER() OVER (PARTITION BY ...)를 활용하면 더 유연하게 그룹별 첫 번째 또는 마지막 행을 선택할 수 있습니다.
마무리
이처럼 GROUP BY 절과 집계 함수, 서브쿼리를 조합하면 그룹화된 데이터 중에서 원하는 행을 손쉽게 정렬하고 선택할 수 있습니다. 실무에서 중복 데이터 제거나 그룹별 대표 값 추출 시 매우 유용하게 활용되는 패턴이니 꼭 익혀두시기 바랍니다.