programmers SQL group by 년, 월, 성별 별 상품 구매 회원 수 구하기

이원일 | Valor·2023년 6월 14일

처리할 일을 끝내고 공부했던 내용 중에 공유하고 싶은 내용이 있어서 글을 남겨봅니다.
많은 의견이나 피드백 공유했으면 좋겠습니다.

저는 데이터베이스에 관심이 많다보니 SQL 문제를 풀면서 쿼리 작성 연습하고 있습니다.
오늘 프로그래머스 SQL group by 문제 중 년,월, 성별 별 상품 구매 회원 수 구하기 문제를 풀었습니다.

문제

programmers SQL group by 년, 월, 성별 별 상품 구매 회원 수 구하기

  • USER_INFO 테이블과 ONLINE_SALE 테이블에서 년, 월, 성별 별로 상품을 구매한 회원수를 집계하는 SQL문을 작성해주세요. 결과는 년, 월, 성별을 기준으로 오름차순 정렬해주세요. 이때, 성별 정보가 없는 경우 결과에서 제외해주세요.
  • 동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다.

풀이

이 문제의 핵심은 group by에 의해 발생하는 중복 데이터를 어떻게 처리할 것인가가 핵심이라고 생각합니다.

처음 완전한 쿼리를 고안해서 작성했더니 오답 행진이었습니다.
이후 데이터 조회 조건을 하나씩 추가하면서 제 쿼리의 허점을 찾으려고 노력했습니다.

SELECT 
	*,
    COUNT(USER_ID) AS USERS
FROM 
    ONLINE_SALE
GROUP BY YEAR(SALES_DATE), MONTH(SALES_DATE)
;

처럼 데이터 값을 조회하는 과정에서 문제의 조건은 년,월 별인데, 일일별로 유저가 반복 주문했을 경우 중복이 발생한다는 것을 알 수 있었습니다.

이를 해결하기 위해서 모든 조회 조건을 추가한 뒤, USER_ID에 DISTINCT 조건을 추가했습니다.

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

이렇게 정답을 맞췄는데,,

최적화

저는 항상 제가 작성한 코드가 못마땅하더라구요. 그래서 어떤 부분을 고칠 수 있을까 고민을 자주합니다.
이번에는 chatGPT 선생님께 코드 개선에 대한 피드백을 요청했습니다.

WHERE 조건문을 JOIN 조건으로 이동시켜 sub query를 없애라

고 조언해주셨습니다.

SELECT 
    YEAR(OS.SALES_DATE) AS YEAR,
    MONTH(OS.SALES_DATE) AS MONTH,
    UI.GENDER, 
    COUNT(DISTINCT OS.USER_ID) AS USERS
FROM 
    ONLINE_SALE OS
INNER JOIN
    USER_INFO UI
ON OS.USER_ID = UI.USER_ID AND UI.GENDER IS NOT NULL
GROUP BY YEAR, MONTH, UI.GENDER
ORDER BY YEAR, MONTH, UI.GENDER;

하지만, 저는 distinct를 사용한 게 아쉬웠었습니다. 해당 키워드는 중복된 데이터를 제거할 때 조회 결과를 검사하며 중복을 제거하기 때문에 비효율적이라고 알고 있기 때문입니다.
하지만 개선 방법을 찾지 못하기도 했고, 직관적이고 최적화된 데이터베이스에서는 빠른 성능을 보인다고 하니, 여기서 코드 개선을 마쳤습니다.

혹시, 쿼리에 다른 의견이 있으시다면 의견을 나누고 싶습니다 !

profile
안녕하세요. 엉덩이 7톤, 365일 성실한 백엔드 개발자, 이원일입니다.

0개의 댓글