-
해커랭크 Top Competitors (다중 JOIN, 필터링)Programing Language/SQL 2025. 6. 15. 23:34반응형
https://www.hackerrank.com/challenges/full-score/problem
Top Competitors | HackerRank
Query a list of top-scoring hackers.
www.hackerrank.com
문제 정의 (영어 -> 한국어 번역 후 문제 파악하기)
줄리아가 방금 코딩 경진대회를 마쳤는데, 리더보드를 만드는 데 여러분의 도움이 필요합니다! 두 개 이상의 과제 에서 만점을 받은 해커의 hacker_id 와 이름을 출력하는 쿼리를 작성하세요. 해커가 만점을 받은 과제의 총 개수를 기준으로 내림차순으로 정렬하세요. 두 명 이상의 해커가 같은 개수의 과제에서 만점을 받은 경우, hacker_id를 기준으로 오름차순으로 정렬하세요 .
1차 풀기
- 풀기 전략
- 단계별 cte
- 해커 id, 이름
- 조건
- 2개 이상 과제에서 만점 받은 해커
- 정렬 기준
- 만점 갯수 내림차순
- 해커 id 오름차순
- 피드백
- 오타 조심
- 만약 groupby를 하나 줄여서 연산 처리 속도를 빠르게 하고 싶다면, 윈도우 함수 사용할 수는 있지만...비추
, max(score) over(partition by hacker_id, challeng_id order by score desc) max_score
, row_number() over(partition by hacker_id, challeng_id order by score desc) rn
- 단계별 cte
/* -- 해커 id, 이름 -- 조건 -- 2개 이상 과제에서 만점 받은 해커 -- 정렬 기준 -- 만점 갯수 내림차순 -- 해커 id 오름차순 -- 테이블 정리 -- Hackers: 해커, 이름 -- Difficulty : 어려움, 만점 점수 -- Challenges : 챌린지 id, 해커(만든) id, 어려움 -- Submissions : 제출 id, 해커(제출) id, 챌린지 id, 점수 -- join 관계 정리 select s.hacker_id , h.name , from submissions s inner join challenges c -- 어려움 붙이기 on s.challenge_id = c.challenge_id inner join difficulty d -- 만점 기준 on c.difficulty_level = d.difficlty_level inner join hackers h -- 해커 이름 붙이기 on s.hacker_id = h.hacker_id */ -- cte 작성 -- 1. 해커별 최고 점수 구하기 with tmp as ( select hacker_id, challenge_id , max(score) max_score from submissions group by hacker_id, challenge_id ) -- 2. 챌린지별 만점 여부 붙여서 해커별로 만점 과제 count , tmp2 as ( select s.hacker_id, h.name , count(distinct s.challenge_id) cnt_full_score from tmp s inner join challenges c -- 어려움 붙이기 on s.challenge_id = c.challenge_id inner join difficulty d -- 만점 기준 on c.difficulty_level = d.difficulty_level and s.max_score = d.score -- 과제별 만점자 필터링 inner join hackers h -- 해커 이름 붙이기 on s.hacker_id = h.hacker_id group by s.hacker_id, h.name ) select hacker_id, name from tmp2 where cnt_full_score >= 2 order by cnt_full_score desc , hacker_id asc ;최적화
- 가독성을 위해서 해커별 만점 과제 정보 만든 후, hacker별 2개이상 만점 수 필터링 과정을 나누기
-- ⚡ 방법 1: CTE 최적화 (권장 - 가독성 + 성능) WITH hacker_max_scores AS ( -- 1단계: 해커별 챌린지별 최고점만 (중복 제거) SELECT hacker_id, challenge_id, MAX(score) AS max_score FROM submissions GROUP BY hacker_id, challenge_id ), full_score_challenges AS ( -- 2단계: 만점받은 챌린지만 필터링 SELECT h.hacker_id, h.challenge_id FROM hacker_max_scores h INNER JOIN challenges c ON h.challenge_id = c.challenge_id INNER JOIN difficulty d ON c.difficulty_level = d.difficulty_level AND h.max_score = d.score ) -- 3단계: 최종 집계 및 필터링 SELECT f.hacker_id, h.name, COUNT(*) AS cnt_full_score FROM full_score_challenges f INNER JOIN hackers h ON f.hacker_id = h.hacker_id GROUP BY f.hacker_id, h.name HAVING COUNT(*) >= 2 ORDER BY cnt_full_score DESC, f.hacker_id ASC;
📊 이 문제에서 윈도우 함수 분석
❌ 윈도우 함수가 부적합한 이유
1️⃣ GROUP BY 최적화 효과 없음
sql-- 현재 문제의 GROUP BY 구조 GROUP BY hacker_id, challenge_id -- 1차 GROUP BY hacker_id, name -- 2차윈도우 함수 핵심 목적인 "GROUP BY 줄이기"가 이 문제에선 적용 안 됨
2️⃣ 불필요한 복잡성 증가
sql-- ❌ 윈도우 함수 방식 (복잡) MAX(score) OVER(PARTITION BY ...), ROW_NUMBER() OVER(...), 중복 제거 -- ✅ 기본 GROUP BY (간단) MAX(score) GROUP BY hacker_id, challenge_id3️⃣ 성능상 이점 없음
- 윈도우 함수: 전체 스캔 + 윈도우 계산 + 필터링
- GROUP BY: 인덱스 활용 + 직접 집계
🎯 언제 윈도우 함수를 써야 하나?
✅ 윈도우 함수가 유리한 경우
예시 1: Contest Leaderboard 타입
sql-- 중첩 GROUP BY 제거 효과 GROUP BY hacker_id, challenge_id → MAX(score) -- 1차 GROUP BY hacker_id → SUM(score) -- 2차 ↓ 윈도우 함수로 한 번에 처리예시 2: 순위 + 원본 데이터
sql-- 각 해커의 순위 + 원본 제출 정보 SELECT hacker_id, submission_id, score, RANK() OVER(ORDER BY score DESC)예시 3: 이전/다음 값 참조
sql-- 이전 제출과 비교 SELECT hacker_id, score, LAG(score) OVER(PARTITION BY hacker_id ORDER BY date)
📈 Top Competitors 특성 분석
이 문제의 구조:
1. submissions → 해커별 챌린지별 최고점 (GROUP BY 필수) 2. difficulty와 JOIN → 만점 여부 확인 (조건부 필터링) 3. 해커별 만점 개수 집계 (GROUP BY 필수)💡 각 단계가 독립적이고 GROUP BY가 최적 → 윈도우 함수 불필요
🏆 결론
Top Competitors에서는:
- ❌ 윈도우 함수: 오버엔지니어링
- ✅ CTE + GROUP BY: 최적 솔루션
- ✅ 단순 명확함: 코테에서 중요
윈도우 함수 vs GROUP BY 판단 기준:
중첩된 GROUP BY 있음? → 윈도우 함수 고려 순위/누적값 필요? → 윈도우 함수 필수 단순 집계만? → GROUP BY가 최적반응형'Programing Language > SQL' 카테고리의 다른 글
해커랭크 Weather Observation Station 20 (중앙값, 윈도우 함수) (0) 2025.06.16 해커랭크 Placements (JOIN, 서브쿼리) (1) 2025.06.15 해커랭크 The Report (JOIN, CASE문, NULL 처리) (1) 2025.06.15 해커랭크 Contest Leaderboard (JOIN, GROUP BY, 조건부 집계) (1) 2025.06.15 데이터베이스 인덱스 활용 (0) 2025.06.15 - 풀기 전략