https://school.programmers.co.kr/learn/courses/30/lessons/131534

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드설명

INNER JOIN + DISTINCT + GROUP BY 를 활용합니다.

 

 

문제에서 유의해야할점입니다.

판매데이터는 2022년 기준 데이터를 가져옵니다.(문제의 조건이 부족합니다.)

코드

SELECT YEAR(OS.SALES_DATE), MONTH(OS.SALES_DATE), COUNT(DISTINCT UI.USER_ID), ROUND((COUNT(DISTINCT UI.USER_ID) / (SELECT COUNT(*) FROM USER_INFO WHERE YEAR(JOINED) = 2021) ), 1)
FROM USER_INFO AS UI
INNER JOIN ONLINE_SALE AS OS
ON YEAR(UI.JOINED) = 2021 AND UI.USER_ID = OS.USER_ID AND YEAR(OS.SALES_DATE) = 2022
GROUP BY YEAR(OS.SALES_DATE), MONTH(OS.SALES_DATE)
ORDER BY YEAR(OS.SALES_DATE) ASC, MONTH(OS.SALES_DATE) ASC

 

ORACLE

SELECT TO_CHAR(OS.SALES_DATE, 'YYYY') AS YEAR, TO_NUMBER(TO_CHAR(OS.SALES_DATE, 'MM')) AS MONTH
    ,COUNT(DISTINCT UI.USER_ID)
    , ROUND(COUNT(DISTINCT UI.USER_ID) / (SELECT COUNT(*) FROM USER_INFO WHERE TO_CHAR(JOINED, 'YYYY') = '2021'), 1) AS PURCHASED_RATIO
FROM ONLINE_SALE OS
INNER JOIN USER_INFO UI
ON OS.USER_ID = UI.USER_ID
WHERE TO_CHAR(UI.JOINED,'YYYY') = '2021'
GROUP BY TO_CHAR(OS.SALES_DATE, 'YYYY'), TO_CHAR(OS.SALES_DATE, 'MM')
ORDER BY YEAR ASC, MONTH ASC

 

위 코드는 SELECT절에 SUBQUERY를 넣었습니다. 그렇기에 항상 데이터를 가져와야 합니다.

이번에는 WITH 절 혹은 CROSS JOIN 및 INNER JOIN을 사용해서 각 데이터에 해당 칼럼을 같이 결합시켜주어서 사용해보겠습니다.

WITH 절 사용시에는 SELECT절에 사용하는 것이 아닌, INNER JOIN, CROSS JOIN을 할떄 사용해야 사용할 수 있습니다.

 

CROSS JOIN을 사용한 코드입니다. GROUP BY 에도 J.TOTAL_COUNT를 넣어야 합니다.

그런데 이떄 , J.TOTAL_COUNT는 항상 고정된 상수값을 반환, 즉 한 행데이터를 반환하기에 큰 의미는 없습니다만, 

이런 경우에는 차라리 서브쿼리로 작성하는 것이 좋아보입니다.

WITH JOINED AS (
    SELECT COUNT(*) AS TOTAL_COUNT FROM USER_INFO
    WHERE TO_CHAR(JOINED, 'YYYY') = '2021'
)

-- 코드를 입력하세요
SELECT TO_CHAR(OS.SALES_DATE, 'YYYY') AS YEAR, TO_NUMBER(TO_CHAR(OS.SALES_DATE, 'MM')) AS MONTH
    ,COUNT(DISTINCT UI.USER_ID)
    , ROUND(COUNT(DISTINCT UI.USER_ID) / (J.TOTAL_COUNT), 1) AS PURCHASED_RATIO
FROM ONLINE_SALE OS
INNER JOIN USER_INFO UI
ON OS.USER_ID = UI.USER_ID
CROSS JOIN JOINED J
WHERE TO_CHAR(UI.JOINED,'YYYY') = '2021'
GROUP BY TO_CHAR(OS.SALES_DATE, 'YYYY'), TO_CHAR(OS.SALES_DATE, 'MM'), J.TOTAL_COUNT
ORDER BY YEAR ASC, MONTH ASC

 

 

만약 CROSS JOIN 말고 INNER JOIN을 사용하고 싶다면? EXIST_CHECK 데이터를 넣어서 하면 되겠지요.

항상 ON 절에 조건이 들어가야 하기 때문입니다. (결합조건)

WITH JOINED AS (
    SELECT COUNT(*) AS TOTAL_COUNT , 1 AS EXIST_CHECK FROM USER_INFO
    WHERE TO_CHAR(JOINED, 'YYYY') = '2021'
)

-- 코드를 입력하세요
SELECT TO_CHAR(OS.SALES_DATE, 'YYYY') AS YEAR, TO_NUMBER(TO_CHAR(OS.SALES_DATE, 'MM')) AS MONTH
    ,COUNT(DISTINCT UI.USER_ID)
    , ROUND(COUNT(DISTINCT UI.USER_ID) / (J.TOTAL_COUNT), 1) AS PURCHASED_RATIO
FROM ONLINE_SALE OS
INNER JOIN USER_INFO UI
ON OS.USER_ID = UI.USER_ID
INNER JOIN JOINED J
ON EXIST_CHECK = 1
WHERE TO_CHAR(UI.JOINED,'YYYY') = '2021'
GROUP BY TO_CHAR(OS.SALES_DATE, 'YYYY'), TO_CHAR(OS.SALES_DATE, 'MM'), J.TOTAL_COUNT
ORDER BY YEAR ASC, MONTH ASC

 

+ Recent posts