하루에 하나씩 공부하기
[해커랭크 Basic Join] Challenges (재도전) 본문
- 문제
해커가 성공한 챌리지가 가장 많은 개수는 모두 출력
나머지는 개수가 유일한 사건만 출력
해커ID, 이름, 성공 개수 출력
Challenges | HackerRank
Print the total number of challenges created by hackers.
www.hackerrank.com
- 키포인트
9몰라몰라모르겠음
- 쿼리
WITH NUM_HAC AS (
SELECT H.HACKER_ID, H.NAME, COUNT(DISTINCT C.CHALLENGE_ID) AS CC
FROM HACKERS H
JOIN CHALLENGES C ON H.HACKER_ID = C.HACKER_ID
GROUP BY H.HACKER_ID, H.NAME
),
MAX_HAC AS (
SELECT MAX(CC) AS MAX_CHAL FROM NUM_HAC
),
COUNT_HAC AS (
SELECT CC, COUNT(*) AS CNT_HAC
FROM NUM_HAC
GROUP BY CHAL_COUNT
)
SELECT N.HACKER_ID, N.NAME, N.CC
FROM NUM_HAC N
JOIN COUNT_HAC C ON N.CC=C.CC
CROSS JOIN MAX_HAC M
WHERE C.CNT_HAC=1
OR N.CC=M.MAX_CHAL
ORDER BY N.CC DESC, N.HACKER_ID ASC;
CTE를 세개나 쓴게 잘한걸까?
NUM_HAC : 해커별로 챌린지 개수 기록
MAX_HAC : 챌린지의 최대값 기록
COUNT_HAC : 챌린지 개수별 기록 (유일한 개수인지 따지기 위해)
# CROSS JOIN한 이유 : MAX_CNT는 단일 행이라 모든 행에 그 값을 붙여주려는 것(상수값 붙이기 용도)
WHERE 절에 OR N.CHAL_COUNT = (SELECT MAX(CHAL_COUNT) FROM NUM_HAC) 해도 동일
- 다른 풀이
WITH COUNTER AS (
SELECT H.HACKER_ID, H.NAME, COUNT(DISTINCT(C.CHALLENGE_ID)) AS CNT
FROM CHALLENGES C
JOIN HACKERS H ON C.HACKER_ID = H.HACKER_ID
GROUP BY H.HACKER_ID, H.NAME
)
SELECT HACKER_ID, NAME, CNT
FROM COUNTER
WHERE CNT = (SELECT MAX(CNT) FROM COUNTER)
OR CNT IN (SELECT CNT FROM COUNTER GROUP BY CNT HAVING COUNT(CNT)=1)
ORDER BY CNT DESC, HACKER_ID;
서브쿼리 쓴 이 풀이가 훨씬 낫다..!
서브쿼리로 CNT를 그룹화하고 HAVING으로 CNT 개수 그룹별 세기