문제: https://datalemur.com/questions/card-launch-success
나의 풀이:
SELECT card_name
, issued_amount
FROM (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY card_name
ORDER BY issue_year, issue_month) AS rownum
FROM monthly_cards_issued) sub
WHERE rownum = 1
ORDER BY issued_amount DESC;
풀긴 했지만 뭔가.. 뭔가 찝찝한 느낌쓰 더 간단하게 풀 수 있을 것 같은데..?
솔루션을 보니 MAKE_DATE() 이라는 내가 모르는 함수를 사용했다
SELECT MAKE_DATE(issue_year, issue_month, 1)
FROM monthly_cards_issued;
괄호안에 인풋값은 MAKE_DATE(year, month, day)가 들어간다.
이 함수도 직관적으로 인풋(연,월,일)값에 대한 날짜를 반환해준다
(CONCAT()을 써도 무방하다)
이 MAKE_DATE()을 어떻게 적용하냐면
WITH card_launch AS (
SELECT
card_name,
issued_amount,
MAKE_DATE(issue_year, issue_month, 1) AS issue_date,
MIN(MAKE_DATE(issue_year, issue_month, 1)) OVER (
PARTITION BY card_name) AS launch_date
FROM monthly_cards_issued
)
SELECT
card_name,
issued_amount
FROM card_launch
WHERE issue_date = launch_date
ORDER BY issued_amount DESC;
위드문(또는 서브쿼리)에 issue_date과 launch_date 컬럼을 만들어서
조건절에서 issue_date = launch_date 이 일치하는 부분을 찾는다
사용하는 데이터에 day는 없고 필요한 정보도 아니기 때문에 임의로 1이라는 숫자를 day에 인풋으로 넣은 것 같다
하지만 내가 썼던 ROW_NUMBER()랑 함수만 좀 다르지
서브쿼리(또는 위드문)를 쓰고 조건절에서 일치하는 데이터만 추출하는 방식은 똑같다
그리고 오히려 더 길고.. 약간 굳이 이렇게 찾아야하나? 라는 생각이 여전히 들었다
그래도 MAKE_DATE() 함수를 알게 된 건 수확이당
사라지지 않는 찝찝함에 디스커션을 확인해봤는데
바로 찝찝함의 원인을 찾았다!
바로 FIRST_VALUE() 사용해서 풀기
SELECT DISTINCT card_name
, FIRST_VALUE(issued_amount) OVER (PARTITION BY card_name
ORDER BY issue_year, issue_month) AS issued_amount
FROM monthly_cards_issued
ORDER BY issued_amount DESC;
이렇게하면 서브쿼리나 위드문없이 한번에 풀 수 있다 하핳
(그리고 디스커션을 보다가 위드문을 cte라고 부른다는 것도 알게 됐따. common table expression의 약자)
오랜만에 보는 함수,, 까먹고있다가 이런게 있었는데? 하는 느낌만 기억이 났나보다
그리고 또 까먹었던 것 - card_name 앞에 디스팅트 붙이기! 디스팅트 없으면 모든 card_name 데이터가 출력되고 옆에 first_value()에 해당하는 값이 반복 출력된다 (-> 중복값 여러개 생성)
그래서 디스팅트를 붙여줘야 고유값을 볼 수 있음