몸과 마음이 건전한 SW 개발자

[SQL-GROUP BY] 프로그래머스 Lv. 3 카테고리 별 도서 판매량 집계하기 [다시 풀어 보기] 본문

SQL/다시 풀어 보기

[SQL-GROUP BY] 프로그래머스 Lv. 3 카테고리 별 도서 판매량 집계하기 [다시 풀어 보기]

스위태니 2024. 12. 23. 16:37

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/144855

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

틀린 코드

WITH TWENTY_TWENTY_TWO_JANUARY AS (
    SELECT
        BOOK_ID,
        SUM(SALES) AS TOTAL_SALES
    FROM BOOK_SALES
    WHERE SALES_DATE BETWEEN '2022-01-01' AND '2022-01-31'
    GROUP BY BOOK_ID
)
SELECT
    B.CATEGORY,
    TTTJ.TOTAL_SALES
FROM BOOK B
LEFT JOIN TWENTY_TWENTY_TWO_JANUARY TTTJ
ON B.BOOK_ID = TTTJ.BOOK_ID
ORDER BY B.CATEGORY;

정답 코드

WITH TWENTY_TWENTY_TWO_JANUARY AS (
    SELECT
        BOOK_ID,
        SUM(SALES) AS TOTAL_SALES
    FROM BOOK_SALES
    WHERE SALES_DATE BETWEEN '2022-01-01' AND '2022-01-31'
    GROUP BY BOOK_ID
), CATEGORY_SALES AS (
    SELECT
        B.CATEGORY,
        SUM(TTTJ.TOTAL_SALES) AS TOTAL_SALES
    FROM BOOK B
    JOIN TWENTY_TWENTY_TWO_JANUARY TTTJ
    ON B.BOOK_ID = TTTJ.BOOK_ID
    GROUP BY B.CATEGORY
)
SELECT
    CATEGORY,
    TOTAL_SALES
FROM CATEGORY_SALES
ORDER BY CATEGORY ASC;

수정 과정

  1. CATEGORY_SALES 서브쿼리 추가:
    • 카테고리별 총 판매량(TOTAL_SALES)을 계산하기 위해 BOOK 테이블과 TWENTY_TWENTY_TWO_JANUARY 결과를 조인하고, 카테고리별로 그룹화했다.
  2. 최종 SELECT 및 정렬:
    • 결과에서 카테고리별 총 판매량을 출력하며, ORDER BY CATEGORY ASC로 카테고리명을 기준으로 오름차순 정렬했다.
  3. LEFT JOIN 제거:
    • BOOK과 TWENTY_TWENTY_TWO_JANUARY 간 조인을 INNER JOIN으로 변경했다.
    • 문제에서 언급된 판매량이 없는 경우는 포함하지 않아도 되므로 LEFT JOIN 대신 INNER JOIN이 적합하다.

 

LEFT JOIN vs INNER JOIN

  1. LEFT JOIN의 특성:
    • LEFT JOIN은 왼쪽 테이블의 모든 행을 유지하면서, 오른쪽 테이블에서 매칭되는 값만 가져온다.
    • 오른쪽 테이블에 매칭되는 값이 없으면, 결과에 NULL로 표시된다.
    예를 들어:
    • 만약 특정 BOOK_ID가 BOOK_SALES 테이블에 존재하지 않는 경우, 해당 도서 정보는 결과에 포함되지만, 판매량(TOTAL_SALES)은 NULL이 된다.
  2. INNER JOIN의 특성:
    • INNER JOIN은 양쪽 테이블에 모두 매칭되는 데이터만 가져온다.
    • 즉, BOOK 테이블과 BOOK_SALES 테이블에 공통으로 존재하는 BOOK_ID만 결과에 포함된다.

왜 LEFT JOIN 대신 INNER JOIN이 적합한가?

  • 문제에서 "판매량이 없는 경우는 결과에서 제외"하라고 명시하지는 않았지만, 2022년 1월에 판매량이 없는 도서는 결과에 포함되지 않아야 한다는 점을 암시하고 있다.

예시:

  • 2022년 1월에 판매된 도서만 카테고리별 판매량을 계산하기로 했으므로, 판매량이 없는 도서는 집계에 포함되지 않아야 한다.

LEFT JOIN의 문제:

  • LEFT JOIN을 사용할 경우, 2022년 1월에 판매량이 없는 도서도 결과에 포함됩니다. 이 도서의 판매량(TOTAL_SALES)은 NULL로 표시된다.
  • 예를 들어, BOOK_ID가 4인 도서가 있다고 가정하고, 2022년 1월에 판매되지 않았다면, 결과에 CATEGORY는 표시되지만 TOTAL_SALES가 NULL이 된다.

INNER JOIN의 적합성:

  • INNER JOIN은 2022년 1월의 판매 데이터가 있는 도서만 결과에 포함한다.
  • 판매량이 0이거나 없는 도서는 아예 결과에 포함되지 않게 된다.
  • 따라서 문제 요구사항에 부합하며, 불필요한 NULL 데이터를 처리할 필요가 없어진다.

느낀점

  • CATEGORY를 그룹화 하지 않은 실수와 LEFT JOIN을 사용하는 실수를 범했다.
  • LEFT JOIN은 왼쪽 테이블은 있으나 오른쪽 테이블에 없으면 NULL로 치환된다.
  • 하지만 공통된 부분만 가져오고 싶다면 INNER JOIN을 쓰는 것이 바람직하다.