[SQL/코드카타] 프로그래머스 - 년, 월, 성별 별 상품 구매 회원 수 구하기(DISTINCT, GROUP BY)

문제

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

 

프로그래머스

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

programmers.co.kr

 


✍️ 문제 요약

  • user_info 테이블과 online_sale 테이블에서  <-- join이 쓰이겠군
  • 년, 월, 성별 별로 상품을 구매한 회원수 집계   <-- group by 하고 집계함수 사용
  • 년, 월, 성별 오름차순 정렬   <-- order by ... asc;
  • 성별 정보가 없는 경우 제외    <-- ifnull(null, '')?  where -- is not null

✍️ 내가 작성한 코드

SELECT YEAR(s.sales_date) YEAR
        , MONTH(s.sales_date) MONTH
        , i.gender
        , COUNT(1) USERS
FROM user_info as i INNER JOIN online_sale as s
  ON i.user_id=s.user_id
WHERE gender is not null
GROUP BY YEAR(s.sales_date)
        , MONTH(s.sales_date)
        , i.gender
ORDER BY YEAR(s.sales_date) ASC
        , MONTH(s.sales_date) ASC
        , i.gender ASC
        
>>> 과거 최소 작성문.. 오답!! >>> 🚨문제가 뭘까?!!
 🚨 문제점 분석!!
- 알고보니 내가 구한 것은 ❌ 년/월/성별 별 "구매 수" 를 집계하여 결과는 나오나 오답이었던 것!
- 그럴게 아니라 ✅ 년/월/성별 별 "구매 회원 수" 를 구해야 함!!!
- 자! 그럼 문제를 알았으니 다시 시도해보자!!

🔍 개선 코드 설명

1. 두 테이블을 JOIN

SELECT ...
FROM online_sale as s
JOIN user_info as i 
  ON s.user_id= i.user_id

2. 성별이 null인 값은 결과에서 제외

WHERE i.gender is not null

3. 년, 월, 성별 별

GROUP BY YEAR(s.sales_date), MONTH(s.sales_date), i.gender

4. 년, 월, 성별 별 구매 회원 수 집계

SELECT YEAR(s.sales_date) YEAR,
         MONTH(s.sales_date) MONTH,
         i.gender GENDER,
         COUNT(DISTINCT s.user_id) AS USERS
                  👆
              🚨중복제거를 해야, "진짜 고객 수"를 구할 수 있음!

✅ 최종 쿼리

SELECT YEAR(s.sales_date) YEAR,
         MONTH(s.sales_date) MONTH,
         i.gender GENDER,
         COUNT(DISTINCT s.user_id) AS USERS
FROM online_sale as s
JOIN user_info as i
  ON s.user_id= i.user_id
WHERE i.gender is not null
GROUP BY YEAR(s.sales_date),
         MONTH(s.sales_date),
         i.gender
ORDER BY YEAR ASC, MONTH ASC, GENDER ASC;

🎯 또 다른 풀이

1) FROM 에 서브쿼리를 넣어 푼 방식!!

SELECT
    T.YEAR,
    T.MONTH,
    T.GENDER,
    COUNT(DISTINCT T.USER_ID) AS USERS
FROM
    (
        SELECT
            YEAR(S.SALES_DATE) AS YEAR,
            MONTH(S.SALES_DATE) AS MONTH,
            U.USER_ID,
            U.GENDER
        FROM
            USER_INFO U INNER JOIN ONLINE_SALE S
            ON U.USER_ID=S.USER_ID
        WHERE U.GENDER IS NOT NULL
    )
    AS T
GROUP BY 
    T.YEAR, T.MONTH, T.GENDER
ORDER BY YEAR ASC, MONTH ASC, GENDER ASC
;
끝.