본문 바로가기

Skill Sets/SQL

[SQL] 재구매가 일어난 상품과 회원 리스트 구하기(프로그래머스/MySQL/Level 2)

SMALL

안녕하세요! 데코입니다!

오늘은 프로그래머스 코딩테스트 연습에 있는 "재구매가 일어난 상품과 회원 리스트 구하기 문제를 포스팅하려고 합니다!

 

바로 포스팅 시작할게요! :)

(출처 : https://school.programmers.co.kr/learn/courses/30/lessons/131536)

1. 문제 :  재구매가 일어난 상품과 회원 리스트 구하기(Lv. 2)

2. 문제 설명

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

ONLINE_SALE 테이블은 아래와 같은 구조로 되어있며

ONLINE_SALE_ID, USER_ID, PRODUCT_ID, SALES_AMOUNT, SALES_DATE는

각각 온라인 상품 판매 ID, 회원 ID, 상품 ID, 판매량, 판매일을 나타냅니다.

 

[ 테이블 구조 ]

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 조합에 대해서는 하나의 판매 데이터만 존재합니다.

 

[ 문제 ]

ONLINE_SALE 테이블에서 동일한 회원이 동일한 상품을 재구매한 데이터를 구하여,

재구매한 회원 ID와 재구매한 상품 ID를 출력하는 SQL문을 작성해주세요.

결과는 회원 ID를 기준으로 오름차순 정렬해주시고

회원 ID가 같다면 상품 ID를 기준으로 내림차순 정렬해주세요.

 

[ 예시 ]

예를 들어 ONLINE_SALE 테이블이 다음과 같다면

ONLINE_SALE_ID USER_ID PRODUCT_ID SALES_AMOUNT SALES_DATE
1 1 3 2 2022-02-25
2 1 4 1 2022-03-01
4 2 4 2 2022-03-12
3 1 3 3 2022-03-31
5 3 5 1 2022-04-03
6 2 4 1 2022-04-06
2 1 4 2 2022-05-11

USER_ID 가 1인 유저가 PRODUCT_ID 가 3, 4인 상품들을 재구매하고,

USER_ID 가 2인 유저가 PRODUCT_ID 가 4인 상품을 재구매 하였으므로,

다음과 같이 결과가 나와야합니다.

 

[ 출력 결과 ]

USER_ID PRODUCT_ID
1 4
1 3
2 4

 

3. 문제 풀이

# 1안
SELECT  USER_ID
        , PRODUCT_ID
  FROM  ONLINE_SALE
 GROUP
    BY  USER_ID
        , PRODUCT_ID
HAVING  COUNT(*) > 1
 ORDER
    BY  USER_ID ASC
        , PRODUCT_ID DESC

이번 문제는 1안 한 가지로 작성했습니다!

#  1안 풀이 설명

# [ 문제 접근 설명 ]

이번 문제의 요구사항을 정리해 보면,

 

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

재구매 이력이 있는 회원 ID와 상품 ID를 나타내는 문제입니다!

 

따라서 '회원 ID'와 '상품 ID'을 각각 의미하는 'USER_ID', 'PRODUCT_ID' 컬럼을 기준으로

'GROUP BY'문을 이용하여 집계하고 

집계 결과에서 2회 이상 구매한 내역만 조회하면 되겠다고 생각했어요!

 

# [ 1안 쿼리 작성 설명 ]

ONLINE_SALE의 테이블에 존재하는 컬럼들이 [출력 결과]에 나와 있는 컬럼들과 동일하게

 

" SELECT "를 통해 " GROUP BY "문에 이용되는 컬럼을 선택

" GROUP BY {컬럼1}, {컬럼2} "를 이용해  'USER_ID', 'PRODUCT_ID' 컬럼별 집계 실행

" HAVING COUNT(*) > 1 "을 이용해 집계 결과에서 COUNT(*)가 2 이상인 데이터만을 조회

" ORDER BY {컬럼} ASC / DESC "를 통해 

'USER_ID' 컬럼을 기준으로 오름차순 정렬, 'PRODUCT_ID' 컬럼을 기준으로 내림차순 정렬

이렇게  쿼리를 작성했습니다!

 


4. 데코의 문제 풀이 후기

이번 문제는 GROUP BY를 통해 집계하고, HAVING 문을 통해 집계 결과에 조건을 넣어 조회하는 문제예요!

 

제가 다룬 문제에서 처음으로 HAVING 문이 나왔네요!

 

SQL에서 HAVING 문은 집계 결과에 조건을 넣어 조건에 만족하는 결과를 조회할 때 사용합니다!

따라서 GROUP BY문 뒤에 사용을 해요!

 

HAVING 문에서는 이전 포스팅에서 다룬 집계함수를 통해 조건을 추가할 수 있어요!

  • MAX : 컬럼의 최댓값을 산출
  • MIN : 컬럼의 최소값을 산출
  • SUM : 컬럼의 값을 합계를 산출
  • COUNT : 컬럼의 갯수를 산출
  • AVG : 컬럼의 평균값을 산출

WHERE 문에서도 조건을 통해 필터링을 하고

HAVING 문에서도 조건을 통해 필터링한다고 해서 혼동하시는 분이 있을 수도 있을 것 같아요! 

WHERE 문과 HAVING 문은 분명한 차이점이 있어요!

 

WHERE 문에서는 데이터에서 ROW(행)에서 조건을 만족하는 데이터만을 필터링하는 구문이고!

HAVING 문은 GROUP BY문을 통해 집계한 이후 만족하는 데이터만을 필터링하는 구문이에요!

 

아래에 간단한 예시를 들어볼게요!

 

[ WHERE 문 : ROW(행)에서 조건을 적용 ]

# DB라는 테이블에서 PRICE가 500을 초과하는 데이터를 조회
# WHRE 문
SELECT  USER_ID
		, PRICE
  FROM  DB
 WHERE  PRICE > 500

WHERE 문은 ROW에서 조건을 만족하는 데이터를 필터링 후 조회

 

[ HAVING 문 : GROUP BY 문을 통해 집계한 결과에서 조건을 적용 ]

# DB라는 테이블에서 USER_ID의 데이터 수를 집계하고 1개를 초과하는 데이터를 조회
# HAVING 문
SELECT  USER_ID
		, COUNT(*)
  FROM  DB
 GROUP
 	BY  USER_ID
HAVING  COUNT(*) > 1

HAVING 문은 GROUP BY로 집계 후 조건을 만족하는 데이터를 필터링 후 조회

HAVING 문 그리고 WHERE 문과의 차이점에 대하여 이해가 가셨나요?

 

집계해서 데이터를 조회할 때, 집계 결과 모두를 봐도 되지만

오늘 다룬 문제처럼 "재구매한 고객"에 관심을 가지고 조회하고 싶을 수 있습니다! 

이때 집계 결과에서 HAVING 문을 통해 조건을 통해 특정한 값만을 확인할 수 있습니다! 

 

이번 문제는 GROUP BY를 통해 집계하고, HAVING 문을 통해 집계 결과에 조건을 넣어 조회하는 문제를 풀어봤습니다!

 

설명이 어려운 부분 혹은 잘 이해가 안 가는 부분은 그리고 더 궁금한 내용이 있다면

언제든지 댓글로 남겨주세요!
빠르게 궁금증을 해결해드릴게요!

공감과 댓글은 큰 힘이 됩니다!
읽어주셔서 감사해요!

 

또 다른 SQL 문제로 찾아뵐게요!

LIST