I want to understand how to make another sql query

The database has a Salary table in which each employee has an ID, as well as a column for the department ID.

Write an SQL query to find the employees who receive the three highest salaries in each department.

Salary:

Id Name Salary DepartmentId
+----+-------+--------+----
| 1 | Petr | 85000 | 1 |
| 2 | Ivan | 80000 | 2 |
| 3 | Alex | 60000 | 2 |
| 4 | Den  | 90000 | 1 |
| 5 | Bob  | 69000 | 1 |
| 6 | Kir  | 85000 | 1 |
| 7 | Mike | 76000 | 1 |

Department:

(DepartmentId, DepartmentName)
      1            IT
      2           Sales

The SQL query should return the following rows (the order of the rows does not matter):

Department  Employee  Salary
+-----------+----------+-----------+
| IT | Den  | 90000 |
| IT | Petr | 85000 |
| IT | Kir  | 85000 |
| IT | Mike | 76000 |
| Sales | Ivan | 80000 |
| Sales | Alex | 60000 |

here is my query:

SELECT d.name as Department,s1.name as Employee,s1.salary
FROM salary s1 
  left join department d on s1.departmentid=d.id
WHERE (SELECT COUNT(DISTINCT s2.salary) 
       from Department d2
       WHERE s2.salary>s1.salary and s2.departmentid=s1.departmentid)<3
ORDER BY d.name,s1.salary DESC;

would like to solve with a window function and CTE

>Solution :

dense_rank() returns the rank of each row within a result set partition, with no gaps in the ranking values.

dense_rank() give the same rank to duplicated rows (exemple salary 85000 both will have order 2)

rn <= 3 with this condition we control how many number of highest salaries should be taken :

with cte as (
  select *, dense_rank() over (partition by DepartmentId order by Salary desc) as rn
  from Salary
)
select d.DepartmentName as Departement, Name as employee, Salary
from cte c
inner join Department d on d.DepartmentId = c.DepartmentId
where rn <= 3
order by c.departmentid, rn

Demo here

Leave a Reply