본문 바로가기
SQL/코딩테스트

[leetcode / MySQL] 184. Department Highest Salary

by Hi_heidi 2024. 1. 30.

문제

💡 Write a solution to find employees who have the highest salary in each of the departments.

Return the result table in any order.

 

테이블 형태

 

풀이

SELECT D.name AS Department
    , E.name AS Employee
    , salary AS Salary
FROM Employee E 
    INNER JOIN Department D ON E.departmentId = D.id
WHERE (departmentId, salary) IN (SELECT departmentId, MAX(salary)
                                FROM Employee
                                GROUP BY departmentId)

 

해설

FROM Employee E 
    INNER JOIN Department D ON E.departmentId = D.id
  • 부서마다 가장 높은 급여를 받은 직원의 부서, 이름, 급여를 출력하는 문제다. 먼저 E 테이블에는 직원정보와 급여가, D 테이블에는 부서가 있으므로 두 테이블을 조인해준다. 직원정보에는 있는데 부서 테이블에는 부서가 없거나, 부서 테이블에는 있는데 직원정보 테이블에는 부서정보가 없는 상황은 존재하지 않을 경우가 높고 존재하더라도 집계 대상에서 제외되므로 INNER JOIN해준다
WHERE (departmentId, salary) IN (SELECT departmentId, MAX(salary)
                                FROM Employee
                                GROUP BY departmentId)
  • ‘부서별’ ‘가장 높은 급여’라는 2가지 조건을 충족해야 하므로 WHERE절 다중컬럼 서브쿼리 문제가 된다. departmentId, salary 를 필터링할 조건 컬럼으로 설정하고 서브쿼리에서 부서id로 그룹핑하여 MAX 값을 산출해 해당 테이블에 있는 데이터만 필터링하는 것으로 조건을 설정해준다. 괄호 사용과 순서 동일에 유의하였다.
  • 부서별 최고 급여는 E테이블의 부서Id와 salary 컬럼만으로도 산출할 수 있기 때문에 서브쿼리에서 테이블을 조인할 필요가 없다. E 테이블로만 산출하고 해당 조건으로 필터링된 데이터에 부서명을 조인해 최종 결과물을 출력하면 된다.
SELECT D.name AS Department
    , E.name AS Employee
    , salary AS Salary
  • 어떤 테이블의 컬럼인지에 유의하여 출력 형식에 맞게 컬럼명을 지정해준다

 

+++ 02.02 수정

2번째 풀이

SELECT Department
    , Employee
    , salary AS Salary
FROM (SELECT RANK() OVER (PARTITION BY departmentId ORDER BY salary DESC) AS ranking
            , e.name AS Employee
            , salary
            , d.name AS Department
        FROM Employee e
            LEFT JOIN Department d ON e.departmentId=d.id 
) row_n
WHERE ranking=1

 

해설

SELECT Department
    , Employee
    , salary AS Salary
FROM (SELECT RANK() OVER (PARTITION BY departmentId ORDER BY salary DESC) AS ranking
            , e.name AS Employee
            , salary
            , d.name AS Department
        FROM Employee e
            LEFT JOIN Department d ON e.departmentId=d.id 
) row_n
WHERE ranking=1
  • 윈도우함수를 사용하면 더 쉽게 풀 수 있다
  • 순위를 매기는 윈도우 함수 중 같은 값에 동일 순위를 부여하는 RANK를 선택했다. DENSE_RANK도 가능하지만 가장 높은 급여자를 찾는 것이 핵심이므로 1위 외 데이터의 랭킹은 순위가 어떻게 부여되도 상관 없으므로 RANK를 썼다. departmentId별 salary를 기준으로 내림차순하여 가장 높은 값에 높은 순위를 부여했다(511. Game Play Analysis1 풀이 참고)
      RANK() DENSE_RANK() ROW_NUMBER()
    동점처리 값이 같으면 같은 순위 부여 값이 같으면 같은 순위 부여 값이 같아도 다른 순위 부여
    동점순위 같은 순위가 여러 개면 중복만큼 건너뜀(ex. 4위 2명, 5위 0명, 6위 1명) 같은 순위가 여러 개라도 건너뜀 없이 부여(ex. 4위 2명, 5위 1명) 행에 번호를 매기는 함수, 같은 순위는 없음
  • 이후 ranking이 1위인 데이터를 필요한 컬럼과 함께 출력해주었다