Post

상품을 구매한 회원 비율 구하기

JOIN

상품을 구매한 회원 비율 구하기


문제 설명

다음은 어느 의류 쇼핑몰에 가입한 회원 정보를 담은 USER_INFO 테이블과 온라인 상품 판매 정보를 담은 ONLINE_SALE 테이블입니다.


USER_INFO 테이블

Column nameTypeNullableDescription
USER_IDINTEGERFALSE회원 ID
GENDERTINYINT(1)TRUE성별 (0: 남자, 1: 여자)
AGEINTEGERTRUE나이
JOINEDDATEFALSE가입일

GENDER 컬럼은 비어있거나 0 또는 1의 값을 가지며 0인 경우 남자를, 1인 경우는 여자를 나타냅니다.


ONLINE_SALE 테이블

Column nameTypeNullableDescription
ONLINE_SALE_IDINTEGERFALSE온라인 상품 판매 ID
USER_IDINTEGERFALSE회원 ID
PRODUCT_IDINTEGERFALSE상품 ID
SALES_AMOUNTINTEGERFALSE판매량
SALES_DATEDATEFALSE판매일

동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다.




문제

USER_INFO 테이블과 ONLINE_SALE 테이블에서 2021년에 가입한 전체 회원들 중 상품을 구매한 회원수와 상품을 구매한 회원의 비율(= 2021년에 가입한 회원 중 상품을 구매한 회원수 / 2021년에 가입한 전체 회원 수)을 년, 월 별로 출력하는 SQL문을 작성해주세요. 상품을 구매한 회원의 비율은 소수점 두번째자리에서 반올림하고, 전체 결과는 년을 기준으로 오름차순 정렬해주시고 년이 같다면 월을 기준으로 오름차순 정렬해주세요.




풀이 과정
  1. 조건 확인
    • 2021년에 가입한 회원만 대상으로 계산해야 함
    • 년, 월별로 그룹화하여 월별로 상품을 구매한 회원 수와 구매 비율을 계산
  2. 회원과 판매 데이터를 결합 (LEFT JOIN)
    • 두 테이블을 USER_ID를 기준으로 조인
    • LEFT JOIN 사용 이유 : 모든 회원 정보 기준으로 판매 정보를 결합해야 하므로
  3. 상품 구매 여부 확인
    • 특정 연도, 월에 동일한 회원이 여러 번 구매했더라도 중복 카운트하면 안 되므로
    • 각 기간별로 고유한 USER_ID를 세기 위해 COUNT(DISTINCT) 이렇게 하자
  4. 2021년에 가입한 전체 회원 수 계산
    • 서브쿼리로 전체 회원 수를 가져와서 나중에 구매 비율을 계산하는 데 써야겠군
  5. 구매 비율 계산
    • 구매 비율은 해당 월에 상품을 구매한 회원의 수 / 전체 회원 수로 계산
    • 소수점 두 번째 자리에서 반올림 해야하니 ROUND 사용하자
  6. 결과 정렬
    • 정렬 기준에 따라 ORDER BY로 결과 정렬
      • 년도와 월 기준으로 ASC 정렬
  • 교훈
    • DISTINCT와 GROUP BY를 같이 사용해서 중복을 방지.. 년도, 월별로 GROUP BY 하는 쿼리… 천재적이다. 어떻게 이런 쿼리 문제가 있지. 새로워서 끄암짝 놀랐다.
    • GROUP BY 한 것을 ORDER BY…. 진짜 천재인가. 나는 아직 부족하다.. 계속 나아가자.




정답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SELECT 
    EXTRACT(YEAR FROM O.SALES_DATE) AS YEAR, 
    EXTRACT(MONTH FROM O.SALES_DATE) AS MONTH,
    COUNT(DISTINCT O.USER_ID) AS PURCHASED_USERS,
    ROUND(COUNT(DISTINCT O.USER_ID) / 
          (SELECT COUNT(*) 
           FROM USER_INFO 
           WHERE EXTRACT(YEAR FROM JOINED) = 2021), 1) AS PURCHASED_RATIO
FROM 
    ONLINE_SALE O
INNER JOIN 
    USER_INFO U ON O.USER_ID = U.USER_ID
WHERE 
    EXTRACT(YEAR FROM U.JOINED) = 2021
GROUP BY 
    EXTRACT(YEAR FROM O.SALES_DATE), 
    EXTRACT(MONTH FROM O.SALES_DATE)
ORDER BY 
    YEAR, 
    MONTH;


Tip

  1. 구매 비율 = 해당 월에 상품을 구매한 회원의 수 / 전체 회원
  2. EXTRACT(YEAR FROM DATE타입컬럼값), EXTRACT(MONTH FROM DATE타입컬럼값) 사용하여 년도와 월별 데이터 그룹화
  3. 소수점 두 번째 자리에서 반올림하기 위해 ROUND() 함수 사용 (둘쨋자리에서 반올림 해야하니 ROUND(컬렴명, 1) <- 이렇게 함수 사용해야함)
    • TO_CHAR(DATE타입컬럼값, ‘YYYY’) 사용하게되면 STRING 반환하므로 ex) 2025-02-12 일 때 STRING의 ‘02’ 반환!
    • EXTRACT(MONTH FROM DATE타입컬럼값) 사용하게되면 NUMBER 반환하므로 ex) 2025-02-12 일 때 NUMBER의 ‘02’ 반환!

SQL Dialect Used: Oracle




개념 확인

  • INNER JOIN
    • 두 테이블의 공통된 컬럼을 기준으로 데이터를 연결
    • 양쪽 테이블 모두에 일치하는 행만 결과에 포함됨
  • EXTRACT() 함수
    • 날짜 데이터에서 특정 연도나 월을 추출하는 데 사용
    • 오라클과 MySQL에서 모두 지원됨
    • EXTRACT(YEAR FROM DATE타입컬럼값) 형태로 사용
    • 추출 가능한 값:
      • 연도: YEAR
      • : MONTH
      • : DAY
      • 시간: HOUR
      • : MINUTE
      • : SECOND
  • COUNT(DISTINCT)
    • 특정 컬럼의 고유한 값(중복 제거된 값)의 개수를 셀 때 사용
  • ROUND() 함수
    • 소수점 이하의 값을 반올림하는 데 사용
    • 기본 구문은 ROUND(컬럼명 or 숫자, 자릿수)이며, 반올림하고자 하는 소수 자릿수를 명시함




상품을 구매한 회원 비율 구하기

This post is licensed under Park Juyoung by the author.

Trending Tags