본문 바로가기

코딩테스트/SQL - 프로그래머스

SQL 고득점 kit(SELECT) - 재구매가 일어난 상품과 회원 리스트 구하기

# 풀이

SELECT user_id
     , product_id
    FROM online_sale
    GROUP BY user_id, product_id
    HAVING COUNT(*) > 1
    ORDER BY user_id, product_id desc;

 해설

- SELECT user_id, product_id : user_id 컬럼의 데이터와 product_id 컬럼의 데이터를 출력하는데,

- FROM online_sale : online_sale이라는 테이블에서,

- GROUP BY user_id, product_id : user_id와 product_id를 기준으로 그룹화 하고(= user_id와 product_id의 조합별로 그룹을 만들고),

- HAVING COUNT(*) >1 : 각 그룹 중 모든 컬럼의 데이터 수가 1보다 큰 행을 찾고,

- ORDER BY user_id, product_id desc; : user_id 기준 오름차순으로 정렬하고 user_id가 같다면 product_id 기준 내림차순으로 정렬한다.

 

상세 해설

아래와 같은 테이블이 있다고 하자.

user_id   product_id
1         a
1         b
2         a
2         a
2         c
3         d
4         e

 

이 때 GROUP BY user_id, product_id를 하면 user_id와 product_id의 조합별로 그룹이 만들어지므로 1-a, 1-b, 2-a, 2-c, 2-c, 3-d, 4-e의 총 6개 그룹이 만들어지게 된다. 그리고 행을 2개 이상 가진 그룹은 2-a 뿐이다.

그러므로 HAVING COUNT(*) > 1 을 하면 출력되는 행은 아래와 같을 것이다.

 

table
user_id   product_id
1         a
1         b
2         a
2         a
2         c
3         d
4         e


SELECT user_id
     , product_id
  FROM table
  GROUP BY user_id, product_id
  HAVING COUNT(*) > 1;
  
 
# 출력

user_id   product_id
2         a

* 원본 문제의 풀이에서 HAVING COUNT(*) > 1에 *을 쓴 이유?

     => *은 모든 컬럼을 의미한다. 즉 모든 컬럼의 값의 개수가 1보다 큰 그룹을 찾는 것이므로, NULL 값이 없는 컬럼이라는 전제 하에 online_sale_id, sales_amount, sales_date 등 어떤 컬럼을 써도 결과는 같다.

 

** 예시 테이블에서 2-a그룹은 행이 2개인데 왜 출력은 하나만 되는가?

     => 'GROUP BY' 절은 그룹화된 결과에서 각 그룹을 대표하는 단일 행만을 생성하기 때문. 보통은 맨 위의 행