Solución
Base de datos
EstrategÃa 1: Regresar las primeras N filas mediante una consulta correlacionada
Algoritmo
Podemos construir una subconsulta correlacionada para identificar los N primeros registros de más de una categorÃa. Dado que la subconsulta correlacionada depende de la consulta principal, la idea que subyace a este enfoque es comparar los valores entre la consulta principal y la subconsulta, de modo que en la subconsulta, como máximo N-1 salarios pueden ser mayores que cada salario seleccionado de la consulta principal.
Para hacer esto, primero construimos la consulta principal. De paso, podemos también unir la tabla Employee
con la tabla Department
en base a la columna departmentId
para obtener el nombre de los departamentos y
renombrar las columnas como se pide en el resultado final.
SELECT d.name AS 'Department',
e1.name AS 'Employee',
e1.salary AS 'Salary'
FROM Employee e1
JOIN Department d
ON e1.departmentId = d.id
En la sub-consulta correlacionada, seleccionamos el número de salarios de la tabla Employee
. Para comparar
los salarios entre la consulta principal y la sub-consulta, nos aseguramos que el departamento es el mismo en
ambas consultas, pero el salario de la sub-consulta es siempre mayor que el salario de la consulta principal.
(
SELECT COUNT(DISTINCT e2.salary)
FROM Employee e2
WHERE e2.salary > e1.salary AND e1.departmentId = e2.departmentId
)
Dado que necesitamos identificar los mejores tres empleados con salario más alto en la consulta principal, y la sub-consulta siempre tiene los salarios más altos que los salarios de la consulta principal, el contador máximo de los salarios más altos en la sub-consulta es dos. Agregamos esta condición como un filtro a la consulta principal.
Implementación
SELECT d.name AS 'Department',
e1.name AS 'Employee',
e1.salary AS 'Salary'
FROM Employee e1
JOIN Department d
ON e1.departmentId = d.id
WHERE
3 > (SELECT COUNT(DISTINCT e2.salary)
FROM Employee e2
WHERE e2.salary > e1.salary AND e1.departmentId = e2.departmentId);
EstrategÃa 2: Regresar las primeras N filas usando la función DENSE_RANK()
Algoritmo
A diferencia del método anterior que utiliza una sub-consulta correlacionada, en este enfoque, ordenamos los salarios en orden descendente, clasificamos a los empleado en base a su salario dentro del departamento, y seleccionamos solo los primeros 3 empleados para cumplir con la salida esperada.
Primero creamos una sub-consulta, la llamamos employee_department
, para clasificar a los empleados. Dado que
la definición de un que gana mucho es aquel que tiene un salario entre los tres salarios más altos del
departamento, podemos utilizar la función DENSE_RANK()
para evitar que los empleados de un mismo
departamento ganen lo mismo. En este paso, también podemos unir la tabla Department
mediante departmentId
para obtener el nombre de los departamentos y renombrar las columnas para el resultado final.
WITH employee_department AS
(
SELECT d.id,
d.name AS Department,
salary AS Salary,
e.name AS Employee,
DENSE_RANK()OVER(PARTITION BY d.id ORDER BY salary DESC) AS rnk
FROM Department d
JOIN Employee e
ON d.id = e.departmentId
)
Ahora, cada empleado tiene una clasificación en base a su salario en orden descendente para cada empleado.
id | Department | Salary | Employee | rnk |
---|---|---|---|---|
1 | IT | 90000 | Max | 1 |
1 | IT | 85000 | Joe | 2 |
1 | IT | 85000 | Randy | 2 |
1 | IT | 70000 | Will | 3 |
1 | IT | 69000 | Janet | 4 |
2 | Sales | 80000 | Henry | 1 |
2 | Sales | 60000 | Sam | 2 |
Con ese rango, podemos seleccionar a los que más ganan. Podemos añadir el filtro para seleccionar los empleados que tienen un rango menor o igual a 3 en la consulta principal.
SELECT Department, Employee, Salary
FROM employee_department
WHERE rnk <= 3
Implementación
WITH employee_department AS
(
SELECT d.id,
d.name AS Department,
salary AS Salary,
e.name AS Employee,
DENSE_RANK()OVER(PARTITION BY d.id ORDER BY salary DESC) AS rnk
FROM Department d
JOIN Employee e
ON d.id = e.departmentId
)
SELECT Department, Employee, Salary
FROM employee_department
WHERE rnk <= 3