2 분 소요

프로그래머스 사이트 링크

📌 문제 설명

다음은 아이스크림 가게의 상반기 주문 정보를 담은 FIRST_HALF 테이블과 7월의 아이스크림 주문 정보를 담은 JULY 테이블입니다.

FIRST_HALF 테이블 구조는 다음과 같으며, SHIPMENT_ID, FLAVOR, TOTAL_ORDER는 각각 아이스크림 공장에서 아이스크림 가게까지의 출하 번호, 아이스크림 맛, 상반기 아이스크림 총주문량을 나타냅니다. FIRST_HALF 테이블의 기본 키는 FLAVOR입니다.

Column name Type Nullable
SHIPMENT_ID INT FALSE
FLAVOR VARCHAR(N) FALSE
TOTAL_ORDER INT FALSE

JULY 테이블 구조는 다음과 같으며, SHIPMENT_ID, FLAVOR, TOTAL_ORDER 은 각각 아이스크림 공장에서 아이스크림 가게까지의 출하 번호, 아이스크림 맛, 7월 아이스크림 총주문량을 나타냅니다. JULY 테이블의 기본 키는 SHIPMENT_ID입니다. JULY테이블의 FLAVORFIRST_HALF 테이블의 FLAVOR의 외래 키입니다. 7월에는 아이스크림 주문량이 많아 같은 맛의 아이스크림이라도 다른 출하 번호를 갖게 되는 경우가 있습니다.


📌 문제

7월 아이스크림 총 주문량과 상반기의 아이스크림 총 주문량을 더한 값이 큰 순서대로 상위 3개의 맛을 조회하는 SQL 문을 작성해주세요.


💻 코드

ver(1) - WITH & UNION ALL 활용 (추천)

두 테이블을 세로로 이어 붙인 뒤, 맛(FLAVOR)별로 그룹화하여 총합을 구하는 직관적인 방식입니다. UNION 대신 중복 제거 과정이 없어 성능이 좋고 데이터 누락 위험이 없는 UNION ALL을 사용했습니다.

WITH ALL_ORDERS AS (
    -- FIRST_HALF 테이블의 맛과 주문량 조회
    SELECT FLAVOR, TOTAL_ORDER FROM FIRST_HALF
    UNION ALL -- 중복을 제거하지 않고 JULY 테이블의 데이터와 세로로 단순히 결합
    -- JULY 테이블의 맛과 주문량 조회
    SELECT FLAVOR, TOTAL_ORDER FROM JULY
)

SELECT FLAVOR
FROM ALL_ORDERS
GROUP BY FLAVOR -- 결합된 임시 테이블을 아이스크림 맛을 기준으로 그룹화
ORDER BY SUM(TOTAL_ORDER) DESC -- 그룹화된 맛별 총 주문량(SUM)을 내림차순 정렬
LIMIT 3; -- 상위 3개의 결과만 출력

ver(2) - JOIN 활용

실무에서 데이터 테이블을 다룰 때 가장 정석적으로 많이 쓰이는 방식입니다. 7월(JULY) 데이터는 같은 맛이 여러 번 출하될 수 있으므로, 먼저 7월 데이터를 맛별로 합산한 서브쿼리를 만든 후 상반기(FIRST_HALF) 데이터와 조인합니다.

SELECT F.FLAVOR
FROM FIRST_HALF F
JOIN (
    -- JULY 테이블은 같은 맛이라도 출하 번호가 다를 수 있으므로, 조인 전에 미리 합산
    SELECT FLAVOR, SUM(TOTAL_ORDER) AS JULY_TOTAL
    FROM JULY
    GROUP BY FLAVOR
) J ON F.FLAVOR = J.FLAVOR -- 맛(FLAVOR)을 기준으로 상반기와 7월 테이블 조인
ORDER BY (F.TOTAL_ORDER + J.JULY_TOTAL) DESC -- 상반기 주문량과 합산된 7월 주문량을 더하여 내림차순 정렬
LIMIT 3; -- 상위 3개만 추출

ver(3) - Window Function (RANK() OVER) 활용

LIMIT 3을 사용하지 않고 윈도우 함수를 활용해 순위를 명시적으로 매긴 후, 3위 이하의 데이터만 필터링하는 방법입니다.

WITH SUM_ORDERS AS (
    -- 상반기와 7월 데이터를 합친 후, 맛별 총 주문량을 계산
    SELECT FLAVOR, SUM(TOTAL_ORDER) AS TOTAL
    FROM (
        SELECT FLAVOR, TOTAL_ORDER FROM FIRST_HALF
        UNION ALL
        SELECT FLAVOR, TOTAL_ORDER FROM JULY
    ) COMBINED -- UNION ALL로 합쳐진 괄호 안의 결과물에 'COMBINED'라는 임시 테이블 이름(Alias) 부여
    GROUP BY FLAVOR
),
RANKED_ORDERS AS (
    -- 맛별 총 주문량을 기준으로 내림차순 순위(RANK) 부여
    SELECT FLAVOR, 
           RANK() OVER (ORDER BY TOTAL DESC) AS rnk
    FROM SUM_ORDERS
)

-- 최종적으로 랭크(rnk)가 3 이하인(1~3등) 맛만 조회
SELECT FLAVOR
FROM RANKED_ORDERS
WHERE rnk <= 3;

댓글남기기