♟️ 알고리즘/Leetcode

[MySQL][Leet Code] 185. Department Top Three Salaries (Hard)

Jerry_K 2025. 3. 8. 00:02

https://leetcode.com/problems/department-top-three-salaries/description/


🗒️SQL 코드 풀이 1

SELECT D1.name AS Department , E1.name AS Employee , E1.salary AS Salary 
    FROM
        (
        SELECT *, DENSE_RANK() OVER (PARTITION BY departmentId  ORDER BY salary DESC) AS salaryRank
            FROM Employee 
        )  E1
    INNER JOIN Department D1 
    ON E1.departmentId = D1.id
    WHERE E1.salaryRank <= 3

 

1. Window Function에 RANK 함수만 잘 알면 해결 가능하다. 

  • ROW_NUMBER / RANK / DENSE_RANK
  • RANK 함수를 쓸 때, 부서별로 순위를 나누기 위해 PARTITION BY도 같이 활용한다.

 

2. 이렇게 한 후 Department 테이블과 조인을 한다.

 

3. 이후 조건에 맞게 필터링하고, 원하는 컬럼을 추출한다. 

 

 

🗒️SQL 코드 풀이 2

SELECT D1.name AS Department, E1.name AS Employee, E1.salary AS Salary 
FROM Employee  E1
INNER JOIN Department D1
ON E1.departmentId = D1.id
WHERE 3 > 
    (
        SELECT COUNT(DISTINCT salary)
        FROM Employee E2
        WHERE E2.salary > E1.salary AND E2.departmentID = E1.departmentID 
    )

 

1. 서브 쿼리를 이용해서 이렇게도 풀 수 있다. 

 

2. 풀이를 설명하면 다음과 같다.

  • 우선 실행 순서는 F - W - G - H - S - O 순으로 실행 됨 (이거는 꼭 필수적으로 알아야 함!)
  • SQL에서 쿼리를 실행하면 각 행의 데이터가 WHERE 조건에 부합하는지 확인 
  • 즉, 행 단위로 쿼리가 실행된다.  
Employee table:
+----+-------+--------+--------------+
| id | name  | salary | departmentId |
+----+-------+--------+--------------+
| 1  | Joe   | 85000  | 1            |
| 2  | Henry | 80000  | 2            |
| 3  | Sam   | 60000  | 2            |
| 4  | Max   | 90000  | 1            |
| 5  | Janet | 69000  | 1            |
| 6  | Randy | 85000  | 1            |
| 7  | Will  | 70000  | 1            |
+----+-------+--------+--------------+
  • 해당 쿼리는 마치 2중 for문 처럼 작동된다. 
  • 먼저 Joe의 salary가 E1.salary에 대입 될 것이다. 
    • 이후 E2.salary는 ( Joe → Max → Randy → Will) 순으로 Joe의 salary와 비교하고 COUNT 된다. 
    • departmentId 가 같다는 전제하에 salary 비교
  • Joe가 끝났으면 다음 E1.salary에는 Henry가 들어간다. 
  • 이렇게 행 단위로 쿼리가 실행된다.

 

 

📌 문제 코멘트 

해당 문제를 포스팅하는 이유는 다음과 같다.

    • Window Function인 Rank에 대해서 잘 몰랐음 
    • 특히 각 부서별 랭크를 나누고 싶어서 GROUP BY를 생각했는데, 굳이 그럴 필요없이 PARTITION BY를 쓰면 끝
    • 쿼리의 작동 방법 (행 단위로 실행되는 구나...)
    • 서브 쿼리로 마치 이중 for문 처럼 구현

 


 

📚문제