[SQL#119]185. Department Top Three Salaries

Gi Woon Lee·2024년 9월 5일

SQL

목록 보기
16/33

TIL: SQL을 사용해 부서별 고소득자 리스트 정리하기

185. Department Top Three Salaries

컨셉

각 부서에서 누가 가장 많은 급여를 받는지 알고 싶어! 이를 위해 각 부서의 "High Earner" 타이틀을 부여할 것이며, 이 타이틀은 부서별로 급여 기준 상위 3명에게 주어진다. 같은 급여를 받는 여러 명이 있을 수도 있기 때문에 순위는 급여 중심으로 평가한다.

한마디로, 급여별 순위를 부여한 다음 1위~3위까지의 당사자를 알아내는 문제다.

중요한 것은 중복값을 허용한다는 것이다. 만약 10달러, 9달러, 9달러, 8달러 순서로 정렬이 된다면 1위~3위는 총 4명이 되는 것이다.

전략

  1. JOIN을 사용해 EmployeeDepartment 테이블을 통합하여 필요한 데이터를 포함한 테이블을 만든다.
  2. 부서별 상위 3명의 급여자를 추출하기 위해 RANK() 또는 DENSE_RANK() 윈도우 함수를 사용한다.

첫 시도

WITH cleaned AS (
    SELECT
        d.name AS Department,
        e.name AS Employee,
        e.salary AS Salary
    FROM Employee e 
    JOIN Department d ON e.departmentId = d.id
)

SELECT 
    Department,
    Employee,
    Salary
FROM 
(
    SELECT 
        *,
        RANK() OVER (PARTITION BY Department ORDER BY Salary) AS ranked
    FROM cleaned
    ORDER BY Department
) ranking
WHERE ranked < 4;

첫 시도가 틀린 이유

  1. RANK() 사용 시 동일한 급여를 가진 사람들에게 동일한 순위가 부여되며, 다음 순위는 건너뛰게 된다. 즉, 1, 2, 2 다음에 4가 오게 된다. 이는 정확한 결과를 방해할 수 있다.
  2. 내림차순 정렬을 위해서는 ORDER BY 절에서 DESC를 명시해주어야 한다.

두 번째 시도 (정답)

WITH sub AS (
    SELECT
        d.name AS Department,
        e.name AS Employee,
        e.salary AS Salary,
        DENSE_RANK() OVER (PARTITION BY d.name ORDER BY e.salary DESC) AS ranked
    FROM Employee e 
    JOIN Department d ON e.departmentId = d.id
)

SELECT Department, Employee, Salary
FROM sub
WHERE ranked <= 3;

핵심 포인트

  • DENSE_RANK() 함수는 동일한 값에 동일한 순위를 부여하고 다음 순위를 건너뛰지 않기 때문에 RANK()보다 적합하다. 예를 들어, 1, 2, 2 다음에 3이 오게 된다.
  • ORDER BY e.salary DESC: DESC를 사용하여 내림차순으로 정렬함으로써 높은 급여가 먼저 평가된다.

보완할 개념

  • 윈도우 함수의 사용: RANK(), DENSE_RANK(), ROW_NUMBER()의 차이를 명확히 이해하고, 상황에 맞는 윈도우 함수를 선택하는 것이 중요하다.
  • 정렬의 중요성: 윈도우 함수 사용 시 ORDER BY의 정렬 기준(오름차순, 내림차순)을 명확히 정의해야 원하는 결과를 얻을 수 있다.

이 TIL을 통해 SQL 윈도우 함수를 이용해 데이터를 그룹별로 순위 매기는 방법과 실수하기 쉬운 부분들을 다시 한번 짚어보게 되었다. 👏

0개의 댓글