ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 해커랭크 The Report (JOIN, CASE문, NULL 처리)
    Programing Language/SQL 2025. 6. 15. 22:49
    반응형

    https://www.hackerrank.com/challenges/the-report/problem

     

    The Report | HackerRank

    Write a query to generate a report containing three columns: Name, Grade and Mark.

    www.hackerrank.com


     

    문제 정의 (영어 -> 한국어 번역 후 문제 파악하기)

    케티는 이브에게 이름 , 등급 , 점수 라는 세 개의 열로 구성된 보고서를 생성하는 과제를 주었습니다. 케티는 8점 미만의 성적을 받은 학생들의 이름을 원하지 않았습니다 . 보고서는 등급을 기준으로 내림차순으로 정렬되어야 합니다. 즉, 높은 성적이 먼저 입력됩니다. 같은 등급(8~10점)을 받은 학생이 두 명 이상인 경우, 해당 학생의 이름을 알파벳순으로 정렬합니다. 마지막으로, 등급이 8점 미만인 경우, 이름에 "NULL"을 사용하고 등급을 내림차순으로 나열합니다. 같은 등급(1~7점)을 받은 학생이 두 명 이상인 경우, 해당 학생의 점수를 오름차순으로 정렬합니다.

     

    1차 풀기

    • 풀기 전략
      • 단계별 cte
        • 이름, 등급, 점수 보고 만들기
        • 조건
          • 8점 미만 이름 null 처리 : case when 사용
          • 등급 매핑 : between 사용
            => 연산자 (>,<)보다 직관적이고 실수가 적음
          • 등급 기준 내림차순 : order by 사용 
            • 8~10점 : 보고 등급 기준 내림차순, 등급이 같은 학생이름 오름차순
            • 8점 미만 : 보고 등급 기준 내림차순, 등급이 같은 경우 점수 오름차순
            • 주의 : case when 조건 then 컬럼 end 정렬 조건
              => 정렬 조건은 case 구문 안에 넣지 않게 조심
      • 단일 쿼리
        • 정렬이기 때문에 cte 사용할 필요 없음
      • 피드백
        • 해당 쿼리는 groupby라던지 특정 순위를 구하는 게 아니므로 굳이 윈도우 사용없이 현재 버전이 최적화임
    /*
    단계별 cte
    -- 이름, 등급, 점수 보고 만들기
    --  조건
    	-- 8점 미만 이름 null 처리
        -- 등급 기준 내림차순
            -- 8~10점 : 보고 등급 기준 내림차순, 등급이 같은 학생이름 오름차순
            -- 8점 미만 : 보고 등급 기준 내림차순, 등급이 같은 경우 점수 오름차순 
    */
    /*
    -- 1. 학생별 등급 생성
    with tmp as (
    	select case when g.grade >= 8 then s.name 
        			else NULL end name
        	, g.grade
            , s.marks
        from students s
        inner join grades g
        	on s.marks between g.min_mark and g.max_mark
    )
    -- 2. 정렬 조건 
    select name
    	, grade
        , marks
    from tmp
    order by grade desc
    	, case when grade >= 8 then name end asc
        , case when grade < 8 then marks end asc
    ;
    */
    -- 최적화
    select case when g.grade >= 8 then s.name 
                else NULL end name
        , g.grade
        , s.marks
    from students s
    inner join grades g
        on s.marks between g.min_mark and g.max_mark
    order by grade desc
    	, case when grade >= 8 then name end asc
        , case when grade < 8 then marks end asc
    ;

     


    🤔 윈도우 함수가 필요한가?

    결론: 전혀 필요 없어요!

    이유:

    1. 단순 정렬 문제: 복잡한 집계나 순위 계산 없음
    2. GROUP BY 없음: 윈도우 함수의 핵심 목적인 "GROUP BY 줄이기" 해당 안 됨
    3. 성능 오버헤드: 불필요한 윈도우 함수는 오히려 성능 저하
    4. 코드 복잡성: 단순한 ORDER BY가 훨씬 직관적

    📊 윈도우 함수 vs 단순 ORDER BY 비교

    ✅ 현재 코드 (최적)

     
    sql
    -- 직관적이고 빠름
    ORDER BY grade DESC, 
             CASE WHEN grade >= 8 THEN name END ASC,
             CASE WHEN grade < 8 THEN marks END ASC

    ❌ 윈도우 함수 (불필요)

     
    sql
    -- 복잡하고 성능 오버헤드
    ROW_NUMBER() OVER(ORDER BY grade DESC, ...)

    성능 차이:

    • 단순 ORDER BY: 1번의 정렬 작업
    • 윈도우 함수: 정렬 + ROW_NUMBER 계산 + 추가 정렬

    🏆 언제 윈도우 함수를 써야 하나?

    ✅ 윈도우 함수가 필요한 경우

     
    sql
    -- 1. 순위 계산
    SELECT name, marks, RANK() OVER(ORDER BY marks DESC)
    
    -- 2. 그룹별 집계 + 원본 행 유지  
    SELECT name, marks, AVG(marks) OVER(PARTITION BY grade)
    
    -- 3. 이전/다음 행 참조
    SELECT name, marks, LAG(marks) OVER(ORDER BY marks)
    
    -- 4. 다중 GROUP BY 최적화
    SELECT ..., MAX(score) OVER(PARTITION BY ...) -- Contest Leaderboard 같은 경우

    ❌ 윈도우 함수가 불필요한 경우

     
    sql
    -- 단순 정렬만 필요한 경우 (The Report)
    ORDER BY column1, column2
    
    -- 단순 집계만 필요한 경우
    SELECT AVG(marks) FROM students GROUP BY grade

    💡 실무 판단 기준

    🎯 윈도우 함수 사용 결정 트리

     
    1. GROUP BY를 여러 번 써야 하나? → YES: 윈도우 함수 고려
    2. 순위나 누적값이 필요한가? → YES: 윈도우 함수 필수
    3. 이전/다음 행 참조가 필요한가? → YES: 윈도우 함수 필수
    4. 단순 정렬/필터링만 필요한가? → YES: 기본 SQL 사용

     

    반응형

    댓글

Designed by Tistory.