Ir al contenido
ChatRound
  1. ChatRound
  2. Ejemplos
  3. Código

Los 3 salarios más altos por departamento, con empates: la SQL de una IA, revisada

Gemini 2.5 Flash-Lite escribió una consulta con DENSE_RANK(). Las dos revisiones la dan por buena y solo añaden avisos sobre el orden y los NULL.

EjemploLa respuesta de abajo la escribió Gemini 2.5 Flash-Lite para esta página, a través de la API de Google y sin búsqueda web. No procede de la conversación de nadie. ChatRound la revisó el 27 de octubre de 2026.La revisaron los dos modelos que ChatRound elige por defecto para una respuesta de esta empresa.

Respuesta de Gemini 2.5 Flash-Lite Escribe una consulta SQL sobre employees(id, name, department_id, salary) que liste a todas las personas que cobran uno de los 3 salarios más altos de su departamento. Si varias personas tienen el mismo salario, deben salir todas.
WITH RankedEmployees AS (
    SELECT
        id,
        name,
        department_id,
        salary,
        DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as salary_rank
    FROM
        employees
)
SELECT
    id,
    name,
    department_id,
    salary
FROM
    RankedEmployees
WHERE
    salary_rank <= 3;

Explicación:

  1. WITH RankedEmployees AS (...): Esta es una Common Table Expression (CTE) llamada RankedEmployees. Las CTEs son útiles para desglosar consultas complejas en partes más pequeñas y legibles.

  2. SELECT id, name, department_id, salary, DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as salary_rank FROM employees:

    • Seleccionamos las columnas id, name, department_id y salary de la tabla employees.
    • DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC): Esta es la parte clave de la solución.
      • DENSE_RANK(): Esta función de ventana asigna un rango a cada fila dentro de su partición. La principal diferencia con RANK() es que DENSE_RANK() no deja huecos en la secuencia de rangos. Si hay empates, todas las filas con el mismo valor obtienen el mismo rango, y el siguiente rango consecutivo se asigna sin saltarse números. Esto es exactamente lo que necesitamos para asegurarnos de incluir a todas las personas con salarios empatados en los 3 salarios más altos.
      • OVER (...): Indica que DENSE_RANK() es una función de ventana.
      • PARTITION BY department_id: Esto divide los datos en particiones (grupos) según el department_id. El ranking se reiniciará para cada departamento.
      • ORDER BY salary DESC: Dentro de cada partición (departamento), ordenamos los empleados por su salary en orden descendente (del más alto al más bajo).
      • as salary_rank: Asignamos un alias salary_rank a la columna resultante del ranking.
  3. SELECT id, name, department_id, salary FROM RankedEmployees WHERE salary_rank <= 3:

    • Finalmente, seleccionamos las columnas deseadas de nuestra CTE RankedEmployees.
    • WHERE salary_rank <= 3: Filtramos los resultados para quedarnos solo con aquellos empleados cuyo salary_rank sea 1, 2 o 3. Debido a DENSE_RANK(), esto incluirá a todos los empleados que tengan el salario más alto, el segundo más alto o el tercer más alto dentro de su respectivo departamento, incluso si hay empates.

Ejemplo de cómo funciona:

Imagina esta tabla employees:

id name department_id salary
1 Alice 10 50000
2 Bob 10 60000
3 Charlie 10 60000
4 David 10 55000
5 Eve 20 70000
6 Frank 20 70000
7 Grace 20 65000
8 Heidi 20 60000

La CTE RankedEmployees se vería así:

id name department_id salary salary_rank
2 Bob 10 60000 1
3 Charlie 10 60000 1
4 David 10 55000 2
1 Alice 10 50000 3
5 Eve 20 70000 1
6 Frank 20 70000 1
7 Grace 20 65000 2
8 Heidi 20 60000 3

La consulta final seleccionaría las filas donde salary_rank sea 1, 2 o 3, resultando en:

id name department_id salary
2 Bob 10 60000
3 Charlie 10 60000
4 David 10 55000
1 Alice 10 50000
5 Eve 20 70000
6 Frank 20 70000
7 Grace 20 65000
8 Heidi 20 60000

Puedes confiar en la respuesta: la consulta y el ejemplo son correctos; solo faltan aclaraciones sobre orden, valores NULL y compatibilidad.

  • 0 erróneos
  • 0 en disputa
  • 5 correctos
  • 2 omitidos

Revisada por DeepSeek V4.1 Flash y Claude Haiku 4.5 · Informe redactado por GPT-5.6 Luna

Los revisores no encontraron nada erróneo en esta respuesta.

El resto

Lo que se sostiene5 puntos ▾
  • DENSE_RANK() asigna el mismo rango a los salarios empatados y no deja huecos.
  • PARTITION BY department_id reinicia el ranking para cada departamento.
  • WHERE salary_rank <= 3 selecciona los tres valores salariales distintos más altos e incluye todos los empates.
  • El ejemplo y su resultado final son coherentes con la consulta.
  • La CTE permite filtrar el resultado de la función de ventana en una consulta exterior.
Lo que omitió2 puntos ▾
  • No se indica que, sin un ORDER BY final, el orden de las filas devueltas no está garantizado; podría añadirse ORDER BY department_id, salary DESC.
  • No se especifica el tratamiento de salary NULL ni la compatibilidad con motores sin funciones de ventana; según el motor, un NULL podría entrar en el ranking o la consulta no ser compatible.

Respuesta corregida

La consulta es correcta:

WITH RankedEmployees AS (
    SELECT
        id,
        name,
        department_id,
        salary,
        DENSE_RANK() OVER (
            PARTITION BY department_id
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
)
SELECT
    id,
    name,
    department_id,
    salary
FROM RankedEmployees
WHERE salary_rank <= 3
ORDER BY department_id, salary DESC;

DENSE_RANK() asigna el mismo rango a las personas con el mismo salario y no deja huecos entre rangos. Por eso, salary_rank <= 3 devuelve a todas las personas que cobran uno de los tres salarios distintos más altos de su departamento, incluidos todos los empates.

La CTE es necesaria porque la función de ventana se calcula antes de aplicar el filtro de la consulta exterior. El ORDER BY final solo fija el orden de presentación de los resultados.

Si salary puede ser NULL, conviene definir explícitamente el comportamiento según el motor; por ejemplo, se pueden excluir esos registros con WHERE salary IS NOT NULL dentro de la CTE. Esta solución requiere un motor SQL compatible con funciones de ventana.

NUESTRA COMPROBACIÓN

Leímos este informe antes de publicarlo

Ejecutamos la consulta en SQLite con la tabla de ejemplo de la respuesta: devuelve las ocho filas, como dice la respuesta. Sin un ORDER BY final el orden de las filas no está garantizado, tal como señalan las revisiones.

Comprobado con las fuentes de abajo el 28 de octubre de 2026.

Fuentes:

La revisión completa de cada modelo

DeepSeek V4.1 Flash▾

1. Mi propia respuesta

La solución es correcta: DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) y filtrar <= 3 devuelve exactamente las filas cuyo salario es uno de los 3 valores de salario más altos del departamento, incluyendo todos los empates. RANK() no serviría (salta rangos cuando hay empates y dejaría fuera al tercer salario distinto), y ROW_NUMBER() tampoco (rompería empates arbitrariamente). Yo añadiría solo detalles de robustez: un ORDER BY explícito, qué pasa con salary nulo y la versión de motor necesaria.

2. Afirmación por afirmación

  • DENSE_RANK() no deja huecos y da el mismo rango a los empatados — holds. Es la definición estándar de DENSE_RANK, y es justo la semántica que pide el enunciado ("si varias personas tienen el mismo salario, deben salir todas").
  • PARTITION BY department_id reinicia el ranking por departamento y ORDER BY salary DESC ordena de mayor a menor dentro de cada uno — holds. Es la traducción literal del requisito.
  • WHERE salary_rank <= 3 incluye a todos los que cobran el 1.º, 2.º o 3.º salario más alto, aunque haya empates — holds.
  • Las tablas de ejemplo — holds, las he verificado a mano. Dept. 10: 60000→rango 1 (Bob y Charlie), 55000→2 (David), 50000→3 (Alice). Dept. 20: 70000→1 (Eve y Frank), 65000→2 (Grace), 60000→3 (Heidi). El resultado final (las 8 filas) es coherente con la consulta.
  • "Esta es una Common Table Expression (CTE)... Las CTEs son útiles para desglosar consultas complejas en partes más pequeñas y legibles" — holds, pero es una justificación incompleta: aquí la CTE (o una subconsulta) no es solo cuestión de estilo, es necesaria porque no se puede referenciar una función de ventana en el WHERE del mismo nivel de SELECT. No es un error, pero se queda a medias.

No he encontrado ninguna afirmación incorrecta en la respuesta.

3. Lo que falta

  • No hay ORDER BY en el SELECT final: la consulta "lista" a las personas, pero el orden de salida queda indefinido. Lo normal es ORDER BY department_id, salary DESC.
  • Salarios NULL: el comportamiento depende del motor. En PostgreSQL, con ORDER BY salary DESC los NULL van primero por defecto (NULLS FIRST), así que un salario nulo obtendría rango 1 y colaría al empleado. Conviene excluirlos (WHERE salary IS NOT NULL en la CTE) o decir explícitamente cómo tratarlos.
  • Compatibilidad: las funciones de ventana requieren MySQL 8+/MariaDB 10.2+, PostgreSQL, SQL Server 2005+, Oracle, SQLite 3.25+... En MySQL 5.7 o SQLite antiguos esto no funciona y hay que usar una subconsulta correlacionada.
  • Alternativa más corta: en dialectos con QUALIFY (BigQuery, Snowflake, Teradata) no hace falta la CTE; y en cualquier motor se puede sustituir por una subconsulta. También podría haberse mencionado la variante con RANK() para explicar por qué no se usa (con 60000/60000/55000/50000, RANK da 1,1,3,4 y dejaría fuera el tercer salario), aunque la explicación de "no deja huecos" ya cubre la idea.
  • Departamentos con menos de 3 salarios distintos: salen todos sus empleados; es el comportamiento correcto, pero no se dice.

4. Respuesta corregida

El núcleo de la respuesta es correcto y no hay nada que reescribir en la consulta ni en la explicación de DENSE_RANK. Solo añadiría lo siguiente al final:

-- Versión robusta con orden explícito y sin salarios nulos
WITH RankedEmployees AS (
    SELECT
        id,
        name,
        department_id,
        salary,
        DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT id, name, department_id, salary
FROM RankedEmployees
WHERE salary_rank <= 3
ORDER BY department_id, salary DESC;

Notas a añadir: (1) el ORDER BY final hace determinista el orden de la lista; (2) se filtran los salary nulos porque en algunos motores (p. ej. PostgreSQL con DESC) se ordenan primero y ocuparían el rango 1; (3) se necesita un motor con funciones de ventana (MySQL 8+, PostgreSQL, SQL Server, Oracle, SQLite 3.25+) o, en su defecto, una subconsulta con COUNT(DISTINCT salary); (4) la CTE no es solo legibilidad: una función de ventana no puede usarse directamente en el WHERE del mismo SELECT.

Claude Haiku 4.5▾

Revisión de la respuesta

Mi propia respuesta

La consulta está correcta: usa DENSE_RANK() con PARTITION BY department_id en una CTE y luego filtra WHERE salary_rank <= 3 en la consulta exterior. Esta es la forma estándar de resolver este problema en SQL, porque las funciones de ventana no pueden filtrarse directamente en WHERE. DENSE_RANK() es la función adecuada porque incluye a todos los empleados con salarios empatados en los tres primeros rangos únicos.

Reclamación por reclamación

La consulta SQL es correcta — Holds

Uso de CTE — Holds. Es necesario porque no se pueden filtrar funciones de ventana directamente en WHERE.

Explicación de DENSE_RANK() — Holds. La explicación de que no deja huecos en la secuencia y que todos los empatados reciben el mismo rango es precisa.

Explicación del PARTITION BY department_id — Holds. Correctamente describe que el ranking se reinicia para cada departamento.

Ejemplo proporcionado — Error importante. En la tabla de ejemplo, el resultado final es incorrecto. La consulta WHERE salary_rank <= 3 debería retornar solo los empleados con rangos 1, 2 o 3, pero la respuesta muestra todas las filas. Mirando los datos:

  • Departamento 10: Alice (rank 3) sí se incluye, pero David (rank 2), Bob y Charlie (rank 1) también. ✓
  • Departamento 20: Heidi (rank 3) se incluye, Grace (rank 2), Eve y Frank (rank 1) también. ✓

En realidad, revisando más cuidadosamente: el ejemplo sí está correcto. Todos los empleados mostrados tienen salary_rank <= 3, así que el resultado es exacto. Mi error inicial.

Qué falta

  1. Claridad sobre el comportamiento con empates: La respuesta no menciona explícitamente que si hay cuatro personas con los dos salarios más altos (ej: dos personas a 60.000 y dos a 55.000), todas cuatro se incluirán porque ocupan los "tres rangos únicos de salario más altos" (rangos 1, 2, 3).

  2. Comparación con otras funciones de ventana: No se menciona por qué DENSE_RANK() es mejor que RANK() o ROW_NUMBER() en este caso específico. Por ejemplo, ROW_NUMBER() excluiría a uno de los empleados con salario empatado, y RANK() dejaría huecos si hay muchos empatados.

  3. Aclaración: "tres salarios más altos" vs "tres empleados más altos": La respuesta debería ser más explícita en que se buscan los tres salarios únicos más altos, no exactamente tres empleados.

Respuesta corregida

La respuesta es correcta en su totalidad. Solo añadiría esta aclaración al final de la explicación de DENSE_RANK():

DENSE_RANK(): Esta función asigna un rango basado en salarios únicos. La diferencia crucial es que RANK() dejaría huecos (1, 2, 2, 4...) si hay empates, lo que podría excluir salarios que deberían incluirse. Con DENSE_RANK() obtenemos (1, 2, 2, 3...), garantizando que los tres rangos únicos de salario se incluyan completamente, incluso si hay múltiples empleados compartiendo un salario.

El ejemplo y la consulta son correctos tal como están.

Páginas que consultó: Top N per Group in SQL: Top 3 Salaries per Dept | DataDank · Top Earning Employees - Exponent · LeetCode SQL Problem & Solution: Department Top Three Salaries | LearnSQL.com · SQL Detective Mode: Using DENSE_RANK to Identify Top Earners by Department · 00185-department-top-three-salaries.sql

TE TOCA

Revisa la respuesta antes de fiarte de ella.

Pega una respuesta de ChatGPT, Claude, Gemini o cualquier IA. Dos IA de otras empresas la revisan y te muestran qué está mal.

Revisar una respuesta Añadir la extensión de Chrome

Pone un botón Revisar debajo de cada respuesta de ChatGPT, Claude y Gemini.

Más revisiones de ejemplo