SQL Study/Programmers

프로그래머스[Lv.3] 물고기 종류 별 대어 찾기

choidawon 2025. 12. 26. 15:48

문제설명

물고기 종류 별로 가장 큰 물고기의 ID, 물고기 이름, 길이를 출력하는 SQL 문을 작성해주세요.
물고기의 ID 컬럼명은 ID, 이름 컬럼명은 FISH_NAME, 길이 컬럼명은 LENGTH로 해주세요.
결과는 물고기의 ID에 대해 오름차순 정렬해주세요.
단, 물고기 종류별 가장 큰 물고기는 1마리만 있으며 10cm 이하의 물고기가 가장 큰 경우는 없습니다.

 

FISH_INFO 테이블

ID FISH_TYPE LENGTH TIME
0 0 30 2021/12/04
1 0 50 2020/03/07
2 0 40 2020/03/07
3 1 20 2022/03/09
4 1 NULL 2020/04/08
5 2 13 2021/04/28
6 0 60 2021/07/27
7 0 55 2021/01/18
8 2 73 2020/01/28
9 1 73 2021/04/08
10 2 22 2020/06/28
11 2 17 2022/12/23

 

FISH_NAME_INFO 테이블

FISH_TYPE FISH_NAME
0 BASS
1 SNAPPER
2 ANCHOVY

 

'BASS' 중 가장 큰 물고기는 60cm 로 물고기 ID 가 6이고, 'SNAPPER' 중 가장 큰 물고기는 73cm 로 물고기 ID가 9입니다. 'ANCHOVY' 중 가장 큰 물고기는 73cm 로 물고기 ID가 8입니다. 따라서 물고기 ID(ID) 에 대해 오름차순 정렬한다면 결과는 다음과 같습니다.

ID FISH_NAME LENGTH
6 BASS 60
8 ANCHOVY 73
9 SNAPPER 73

 

코드설명

INNER JOIN의 의미

INNER JOIN은
👉 두 테이블 모두에 존재하는 데이터만 결과로 반환한다.

즉,

  • FISH_INFO에 존재하고
  • 동시에 FISH_NAME_INFO에도 존재하는 FISH_TYPE

인 경우만 출력된다.


✅ 이 문제에서 INNER JOIN이 적절한 이유

이 쿼리의 목적은:

“물고기 종류별 최대 길이 물고기의 ID, 이름, 길이”를 정확히 출력하는 것

여기서 물고기 이름(FISH_NAME)은 필수 정보

  • FISH_NAME_INFO에 없는 FISH_TYPE이라면?
    • 이름을 알 수 없는 물고기
    • 문제 의도상 출력할 가치가 없는 데이터

그래서:

  • 이름이 매칭되지 않는 행은 아예 결과에서 제외하는 것이 맞고
  • 이 동작을 자연스럽게 보장해주는 것이 INNER JOIN

3) LEFT JOIN을 쓰면 왜 문제가 될 수 있을까?

LEFT JOIN의 의미

LEFT JOIN은
👉 왼쪽 테이블(FISH_INFO)의 데이터는 전부 유지하고,
오른쪽 테이블이 매칭되지 않으면 NULL을 채운다.


LEFT JOIN 사용 시 발생 가능한 결과

만약 FISH_NAME_INFO에 없는 타입이 있다면:

I.IDI.FISH_TYPEI.LENGTHN.FISH_NAME

 

10 99 50 NULL
  • 최대 길이 조건은 만족했지만
  • 이름이 NULL인 물고기가 결과에 포함됨
  • WHERE: “종류별 최대 길이”인 행만 남기는 핵심3-1) 서브쿼리(괄호 안)부터 해석
    • GROUP BY FISH_TYPE : 물고기를 종류별로 묶고
    • MAX(LENGTH) : 각 종류에서 가장 큰 길이를 구함
    결과 : 즉 “종류 1의 최대 길이는 30, 종류 2의 최대 길이는 45 …” 같은 요약표가 만들어진다.
     
    (I.FISH_TYPE, I.LENGTH) IN (서브쿼리 결과)
    이건 튜플 비교(2개 컬럼을 한 쌍으로 비교)
    • I.FISH_TYPE = 서브쿼리의 FISH_TYPE 이면서
    • I.LENGTH = 그 타입의 LENGTH_MAX
    둘 다 동시에 만족하는 행만 남김
    • “해당 타입에서 LENGTH가 최대인 물고기(들)”만 걸러짐.
    만약 어떤 타입에서 최대 길이가 45인 물고기가 2마리면, (그 타입, 45) 조합이 같으니까 2마리 모두 결과에 포함.
    ORDER BY: 출력 정렬
    • 최종 결과를 ID 오름차순으로 정렬

코드

SELECT I.ID, N.FISH_NAME, I.LENGTH
FROM FISH_INFO I
INNER JOIN FISH_NAME_INFO N
ON N.FISH_TYPE = I.FISH_TYPE
WHERE (I.FISH_TYPE, I.LENGTH) IN (
    SELECT FISH_TYPE, MAX(LENGTH) AS LENGTH_MAX
    FROM FISH_INFO
    GROUP BY FISH_TYPE
)
ORDER BY ID

 

출처 : https://school.programmers.co.kr/learn/courses/30/lessons/293261