안녕하세요! 데코입니다!
오늘은 프로그래머스 코딩테스트 연습에 있는 "년, 월, 성별 별 상품 구매 회원 수 구하기" 문제를 포스팅하려고 합니다!
바로 포스팅 시작할게요! :)
(출처 : https://school.programmers.co.kr/learn/courses/30/lessons/131532)
1. 문제 : 년, 월, 성별 별 상품 구매 회원 수 구하기(Lv. 4)
2. 문제 설명
다음은 어느 의류 쇼핑몰에 가입한 회원 정보를 담은 USER_INFO 테이블과
온라인 상품 판매 정보를 담은 ONLINE_SALE 테이블입니다.
USER_INFO 테이블은 아래와 같은 구조로 되어있으며 USER_ID, GENDER, AGE, JOINED는
각각 회원 ID, 성별, 나이, 가입일을 나타냅니다.
[ 테이블 구조('USER_INFO') ]
COLUMN NAME | TYPE | NULLABLE |
USER_ID | INTEGER | FALSE |
GENDER | TINYINT(1) | TRUE |
AGE | INTEGER | TRUE |
JOINED | DATE | FALSE |
GENDER 컬럼은 비어있거나 0 또는 1의 값을 가지며
0인 경우 남자를, 1인 경우는 여자를 나타냅니다.
ONLINE_SALE 테이블은 아래와 같은 구조로 되어있며,
ONLINE_SALE_ID, USER_ID, PRODUCT_ID, SALES_AMOUNT, SALES_DATE는
각각 온라인 상품 판매 ID, 회원 ID, 상품 ID, 판매량, 판매일을 나타냅니다.
[ 테이블 구조('ONLINE_SALE') ]
COLUMN NAME | TYPE | NULLABLE |
ONLINE_SALE_ID | INTEGER | FALSE |
USER_ID | INTEGER | FALSE |
PRODUCT_ID | INTEGER | FALSE |
SALES_AMOUNT | INTEGER | FALSE |
SALES_DATE | DATE | FALSE |
동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다.
[ 문제 ]
USER_INFO 테이블과 ONLINE_SALE 테이블에서
년, 월, 성별 별로 상품을 구매한 회원수를 집계하는 SQL문을 작성해주세요.
결과는 년, 월, 성별을 기준으로 오름차순 정렬해주세요.
이때, 성별 정보가 없는 경우 결과에서 제외해주세요.
[ 예시 ]
예를 들어 USER_INFO 테이블이 다음과 같고
USER_ID | GENDER | AGE | JOINED |
1 | 1 | 26 | 2021-06-01 |
2 | NULL | NULL | 2021-06-25 |
3 | 0 | NULL | 2021-06-30 |
4 | 0 | 31 | 2021-07-03 |
5 | 1 | 25 | 2021-07-09 |
6 | 1 | 33 | 2021-07-14 |
ONLINE_SALE 테이블이 다음과 같다면
ONLINE_SALE_ID | USER_ID | PRODUCT_ID | SALES_AMOUNT | SALES_DATE |
1 | 1 | 54 | 1 | 2022-01-01 |
2 | 1 | 3 | 2 | 2022-01-25 |
3 | 4 | 34 | 1 | 2022-01-30 |
4 | 6 | 253 | 3 | 2022-02-03 |
5 | 2 | 31 | 2 | 2022-02-09 |
6 | 5 | 35 | 1 | 2022-02-14 |
7 | 5 | 57 | 1 | 2022-02-18 |
2022년 1월에 상품을 구매한 회원은
USER_ID 가 1(GENDER=1), 4(GENDER=0)인 회원들이고,
2022년 2월에 상품을 구매한 회원
USER_ID 가 2(GENDER=NULL), 5(GENDER=1), 6(GENDER=1)인 회원들 이므로,
년, 월, 성별 별로 상품을 구매한 회원수를 집계하고,
년, 월, 성별을 기준으로 오름차순 정렬하면 다음과 같은 결과가 나와야 합니다.
[ 출력 결과 ]
YEAR | MONTH | GENDER | USERS |
2022 | 1 | 0 | 1 |
2022 | 1 | 1 | 1 |
2022 | 2 | 1 | 2 |
3. 문제 풀이
-- 1안
SELECT YEAR(A.SALES_DATE) AS YEAR
, MONTH(A.SALES_DATE) AS MONTH
, B.GENDER
, COUNT(DISTINCT A.USER_ID) AS USERS
FROM ONLINE_SALE A
LEFT
JOIN USER_INFO B
ON A.USER_ID = B.USER_ID
WHERE B.GENDER = 0
OR B.GENDER = 1
GROUP
BY YEAR(A.SALES_DATE)
, MONTH(A.SALES_DATE)
, B.GENDER
ORDER
BY YEAR ASC
, MONTH ASC
, GENDER ASC
이번 문제는 총 1안 한 가지로 작성했습니다!
# 1안 풀이 설명
# [ 문제 접근 설명 ]
문제를 읽고 조건에 맞는 쿼리를 작성하기 위해서 다음과 같이 네 가지 단계로 진행했어요!
1. ONLINE_SALE 테이블을 기준으로 USER_INFO 테이블과 조인하기(JOIN)
2. GENDER 값이 존재하는 데이터만 조회하기(WHERE)
3. 년도, 월, 성별 별 회원 수 집계하기(GROUP BY)
4. 년도, 월, 성별 기준으로 정렬(ORDER BY)
# [ 1안 쿼리 작성 설명 ]
1 첫 번째 단계에서는 ONLINE_SALE 테이블을 기준으로 USER_INFO 테이블과 조인을 했습니다!
공통으로 가지고 있는 컬럼인 USER_ID를 이용해서 ON 조건을 써주었고
ONLINE_SALE 테이블을 기준으로 LEFT JOIN 하였습니다.
SELECT *
FROM ONLINE_SALE A
LEFT
JOIN USER_INFO B
ON A.USER_ID = B.USER_ID
2 두 번째 단계에서는 GENDER 값이 존재하는 데이터만 필터링해주었어요!
저번 포스팅에서 적은 것과 같이 최대한 NOT 사용을 지양해서
WHERE문에서 GENDER가 0 또는 1인 값을 OR을 이용해서 나타내었습니다.
SELECT *
FROM ONLINE_SALE A
LEFT
JOIN USER_INFO B
ON A.USER_ID = B.USER_ID
WHERE B.GENDER = 0
OR B.GENDER = 1
3 세 번째 작업은 년도, 월, 성별 별로 GROUP BY를 이용해 집계해주었습니다!
또 회원 수를 구하기 위해서 COUNT 함수와 DISTINCT 함수를 이용해서 산출했어요!
DISTINCT를 사용한 이유는, 동일한 유저가 같은 날에 다른 주문을 했을 수도 있으니까
고유한 회원의 수를 세기 위해서는 DISTINCT를 사용했습니다!
SELECT YEAR(A.SALES_DATE) AS YEAR
, MONTH(A.SALES_DATE) AS MONTH
, B.GENDER
, COUNT(DISTINCT A.USER_ID) AS USERS
FROM ONLINE_SALE A
LEFT
JOIN USER_INFO B
ON A.USER_ID = B.USER_ID
WHERE B.GENDER = 0
OR B.GENDER = 1
GROUP
BY YEAR(A.SALES_DATE)
, MONTH(A.SALES_DATE)
, B.GENDER
4 마지막으로는 요구사항에 맞게 정렬했어요!
년(YEAR) 기준 오름차순 정별,
월(MONTH) 기준 오름차순 정렬.
그리고 성별(GENDER) 기준 오름차순으로 정렬했습니다!
SELECT YEAR(A.SALES_DATE) AS YEAR
, MONTH(A.SALES_DATE) AS MONTH
, B.GENDER
, COUNT(DISTINCT A.USER_ID) AS USERS
FROM ONLINE_SALE A
LEFT
JOIN USER_INFO B
ON A.USER_ID = B.USER_ID
WHERE B.GENDER = 0
OR B.GENDER = 1
GROUP
BY YEAR(A.SALES_DATE)
, MONTH(A.SALES_DATE)
, B.GENDER
ORDER
BY YEAR ASC
, MONTH ASC
, GENDER ASC
4. 데코의 문제 풀이 후기
이번 문제는 LEVEL 4인 문제임에도
두 테이블을 JOIN하고 GROUP BY하면 되는 어렵지 않은 문제네요!
다른 분들이 실수할 만한 것으로는 DISTINCT 함수를 빼먹는 거 정도 있을 것 같습니다!
이 외에는 이전 문제들에서 모두 다룬 것들을 이용해서
따로 코멘트할 것은 없네요!
혹시나 더 좋은 쿼리나 어렵게 느껴지신 부분이 있다면 댓글로 남겨주세요!
이번 문제는 2개의 테이블을 결합하고 날짜에서 년, 월을 추출하는 것과
GROUP BY와 집계 함수를 통해 회원수를 산출하는 쿼리를 작성해 보았습니다!
설명이 어려운 부분 혹은 잘 이해가 안 가는 부분
그리고 더 궁금한 내용이 있다면
언제든지 댓글로 남겨주세요!
빠르게 궁금증을 해결해 드릴게요!
공감과 댓글은 큰 힘이 됩니다!
오늘도 블로그 방문해 주시고
포스팅 읽어주셔서 감사합니다!
'Skill Sets > SQL' 카테고리의 다른 글
[SQL] 즐겨찾기가 가장 많은 식당 정보 출력하기(프로그래머스/MySQL/Level 3) (53) | 2023.11.19 |
---|---|
[SQL] 오프라인/온라인 판매 데이터 통합하기(프로그래머스/MySQL/Level 4) (69) | 2023.11.11 |
[SQL] SQL 쿼리 양식 및 작성 규칙 (66) | 2023.10.21 |
[SQL] 상품 별 오프라인 매출 구하기(프로그래머스/MySQL/Level 2) (73) | 2023.10.17 |
[SQL] 진료과별 총 예약 횟수 출력하기(프로그래머스/MySQL/Level 2) (60) | 2023.09.19 |