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

slackmart blog © 2024