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

MySQL SELECT 문으로 여러 열의 고유한 값 조회하기(DISTINCT 활용)

MySQL에서 DISTINCT 키워드는 단일 열뿐만 아니라 여러 열을 조합한 기준으로도 중복을 제거할 수 있습니다. 다만 실무에서는 특정 열(예: 학생 ID)별로 가장 최신 레코드 하나씩만 조회해야 하는 경우가 많은데, 이럴 때는 DISTINCT보다 서브쿼리와 GROUP BY, MAX() 함수를 조합하는 방식이 더 효과적입니다.

이 글에서는 예제 테이블을 만들고, 학생별로 마지막 강의 기록만 조회하는 쿼리를 단계별로 살펴보겠습니다.

1단계: 예제 테이블 생성

먼저 강사 ID, 학생 ID, 기술 과목을 저장할 테이블을 생성합니다.

mysql> create table selectDistinctDemo
-> (
-> InstructorId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> StudentId int,
-> TechnicalSubject varchar(100)
-> );
Query OK, 0 rows affected (0.50 sec)

2단계: 샘플 데이터 삽입

INSERT 문을 사용해 학생별로 여러 개의 과목 기록을 넣어줍니다. 일부러 같은 학생(121, 298)이 여러 행에 걸쳐 등장하도록 구성했습니다.

mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(121,'Java');
Query OK, 1 row affected (0.15 sec)
mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(121,'MongoDB');
Query OK, 1 row affected (0.16 sec)
mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(121,'MySQL');
Query OK, 1 row affected (0.15 sec)
mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(298,'Python');
Query OK, 1 row affected (0.11 sec)
mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(298,'SQL Server');
Query OK, 1 row affected (0.15 sec)
mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(397,'C#');
Query OK, 1 row affected (0.13 sec)

3단계: 전체 데이터 확인

SELECT 문으로 테이블의 모든 레코드를 조회해 보겠습니다.

mysql> select *from selectDistinctDemo;

실행 결과는 다음과 같습니다.

+--------------+-----------+------------------+
| InstructorId | StudentId | TechnicalSubject |
+--------------+-----------+------------------+
| 1 | 121 | Java |
| 2 | 121 | MongoDB |
| 3 | 121 | MySQL |
| 4 | 298 | Python |
| 5 | 298 | SQL Server |
| 6 | 397 | C# |
+--------------+-----------+------------------+
6 rows in set (0.00 sec)

현재 총 6개의 레코드가 있으며, 학생 121은 3개, 학생 298은 2개의 기록을 가지고 있습니다.

4단계: 학생별 고유한 레코드만 조회하기

여기서 목표는 학생 ID별로 마지막(가장 큰 InstructorId를 가진) 레코드 한 건씩만 가져오는 것입니다. 이를 위해 서브쿼리에서 GROUP BY와 MAX()를 사용해 각 학생의 최대 InstructorId를 구하고, 메인 쿼리의 WHERE 절 IN 조건과 연결합니다.

mysql> select InstructorId,StudentId,TechnicalSubject from selectDistinctDemo
-> where InstructorId IN
-> (
-> select max(InstructorId) from selectDistinctDemo
-> group by StudentId
-> )
-> order by InstructorId desc;

실행 결과는 다음과 같습니다.

+--------------+-----------+------------------+
| InstructorId | StudentId | TechnicalSubject |
+--------------+-----------+------------------+
| 6 | 397 | C# |
| 5 | 298 | SQL Server |
| 3 | 121 | MySQL |
+--------------+-----------+------------------+
3 rows in set (0.10 sec)

결과 분석 및 핵심 포인트

원래 6개였던 레코드가 학생별로 하나씩만 남아 총 3개로 줄어든 것을 확인할 수 있습니다.

  • 서브쿼리 부분: select max(InstructorId) from selectDistinctDemo group by StudentId가 학생 ID별로 가장 큰 InstructorId(즉, 가장 나중에 등록된 기록)를 반환합니다.
  • 메인 쿼리 부분: 해당 InstructorId에 해당하는 행들만 필터링하여 학생당 정확히 한 개의 레코드를 가져옵니다.
  • ORDER BY 절: InstructorId desc로 정렬해 최근 기록 순으로 결과를 보기 좋게 정렬합니다.

이 패턴은 DISTINCT만으로는 해결하기 어려운 "그룹별 최신 레코드 조회" 요구 사항을 처리할 때 매우 유용하며, MySQL 8.0 이상이라면 윈도우 함수인 ROW_NUMBER() OVER(PARTITION BY ...)를 활용하는 방법도 좋은 대안입니다.