처리할 일을 끝내고 공부했던 내용 중에 공유하고 싶은 내용이 있어서 글을 남겨봅니다.
많은 의견이나 피드백 공유했으면 좋겠습니다.
저는 데이터베이스에 관심이 많다보니 SQL 문제를 풀면서 쿼리 작성 연습하고 있습니다.
오늘 프로그래머스 SQL group by 문제 중 년,월, 성별 별 상품 구매 회원 수 구하기 문제를 풀었습니다.
programmers SQL group by 년, 월, 성별 별 상품 구매 회원 수 구하기
이 문제의 핵심은 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를 사용한 게 아쉬웠었습니다. 해당 키워드는 중복된 데이터를 제거할 때 조회 결과를 검사하며 중복을 제거하기 때문에 비효율적이라고 알고 있기 때문입니다.
하지만 개선 방법을 찾지 못하기도 했고, 직관적이고 최적화된 데이터베이스에서는 빠른 성능을 보인다고 하니, 여기서 코드 개선을 마쳤습니다.
혹시, 쿼리에 다른 의견이 있으시다면 의견을 나누고 싶습니다 !