Consulta SQL para encontrar el N-ésimo salario más alto de una tabla de salarios


¿Cómo puedo encontrar el enésimo salario más alto en una tabla que contiene salarios en SQL Server?

Author: LittleBobbyTables, 2010-10-03

11 answers

Puede usar una expresión de Tabla Común (CTE) para derivar la respuesta.

Digamos que tienes los siguientes salarios en la tabla Salarios:

 EmployeeID  Salary
--------------------
     10101   50,000
     90140   35,000
     90151   72,000
     18010   39,000
     92389   80,000

Usaremos:

DECLARE @N int
SET @N = 3  -- Change the value here to pick a different salary rank

SELECT Salary
FROM (
    SELECT row_number() OVER (ORDER BY Salary DESC) as SalaryRank, Salary
    FROM Salaries
) as SalaryCTE
WHERE SalaryRank = @N

Esto creará un número de fila para cada fila después de que se haya ordenado por el Salario en orden descendente, luego recuperará la tercera fila (que contiene el tercer registro más alto).


Para aquellos de ustedes que no quieren un CTE (o están atascados en SQL 2000):

[Nota: esto funciona notablemente peor que el ejemplo anterior; ejecutarlos lado a lado con un plan de ejecución muestra un costo de consulta del 36% para el CTE y del 64% para la subconsulta]:

SELECT TOP 1 Salary
FROM 
(
    SELECT TOP N Salary
    FROM Salaries
    ORDER BY Salary DESC
) SalarySubquery
ORDER BY Salary ASC

Donde N es definido por usted.

SalarySubquery es el alias que le he dado a la subconsulta, o la consulta que está entre paréntesis.

Lo que hace la subconsulta es seleccionar los N salarios superiores (diremos 3 en este caso), y los ordena por el el mejor salario.

Si queremos ver el tercer salario más alto, la subconsulta devolvería:

 Salary
-----------
80,000
72,000
50,000

La consulta externa luego selecciona el primer salario de la subconsulta, excepto que esta vez lo ordenamos ascendentemente, que ordena de menor a mayor, por lo que 50,000 sería el primer registro ordenado ascendentemente.

Como puede ver, 50,000 es de hecho el tercer salario más alto en el ejemplo.

 33
Author: LittleBobbyTables,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-11 18:59:02

Puedes usar row_number para elegir una fila específica. Por ejemplo, el 42º salario más alto:

select  *
from    (
        select  row_number() over (order by Salary desc) as rn
        ,       *
        from    YourTable
        ) as Subquery
where   rn = 42

Las funciones de ventana como row_number solo pueden aparecer en las cláusulas select o order by. La solución es colocar el row_number en una subconsulta.

 12
Author: Andomar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-03 14:14:03
select MIN(salary) from (
select top 5 salary from employees order by salary desc) x
 6
Author: Mayank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-20 10:07:33
EmpID   Name    Salary
1   A   100
2   B   800
3   C   300
4   D   400
5   E   500
6   F   200
7   G   600

SELECT * FROM Employee E1
WHERE (N-1) = (
                SELECT COUNT(DISTINCT(E2.Salary))
                FROM Employee E2
                WHERE E2.Salary > E1.Salary
              )

Supongamos que desea encontrar el 5º salario más alto, lo que significa que hay un total de 4 empleados que tienen un salario mayor que el 5º empleado más alto. Así que para cada fila de la consulta externa comprobar el número total de salarios que son mayores que el salario actual. La consulta externa funcionará para 100 primero y verificará el número de salarios superiores a 100. Será 6, no coinciden (5-1) = 6 donde cláusula de outerquery. Luego para 800, y comprobar el número de salarios superiores a 800, 4=0 falso entonces trabajar para 300 y finalmente hay totalmente 4 registros en la tabla que son mayores que 300. Por lo tanto, 4=4 cumplirá con la cláusula where y volverá 3 C 300.

 4
Author: Rajiv Saxena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-25 13:28:17

Pruébalo...

use table_name
select MAX(salary)
from emp_salary
WHERE marks NOT IN (select MAX(marks)
from student_marks )
 2
Author: Himanshu Namdeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-10 09:58:51

Forma sencilla SIN utilizar ninguna característica especial específica de Oracle, MySQL, etc. Supongamos que en la tabla de EMPLEADOS los salarios se pueden repetir. Utilice query para averiguar el rango de cada ID.

select  *
from  (
select tout.sal, id, (select count(*) +1 from (select distinct(sal) distsal from     
EMPLOYEE ) where  distsal >tout.sal)  as rank  from EMPLOYEE tout
) result
order by rank

Primero averiguamos los distintos salarios. A continuación, nos enteramos de la cuenta de distintos salarios mayores que cada fila. Esto no es más que el rango de esa identificación. Para el salario más alto, este recuento será cero. Así que '+1 ' se hace para comenzar el rango desde 1.

Ahora podemos obtener IDs en el Enésimo rango agregando la cláusula where a la anterior consulta.

select  *
from  (
select tout.sal, id, (select count(*) +1 from (select distinct(sal) distsal from     
EMPLOYEE ) where  distsal >tout.sal)  as rank  from EMPLOYEE tout
) result
where rank = N;
 1
Author: Kaushik Lele,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-16 05:25:54

No olvides usar la palabra clave distinct: -

SELECT TOP 1 Salary
FROM 
(
    SELECT Distinct TOP N Salary
    FROM Salaries
    ORDER BY Salary DESC
) SalarySubquery
ORDER BY Salary ASC
 1
Author: Hassan Arafat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-02 06:41:20

Solución 1: Este SQL para encontrar el enésimo salario más alto debería funcionar en SQL Server, MySQL, DB2, Oracle, Teradata y casi cualquier otro RDBMS: (nota: bajo rendimiento debido a subconsulta)

SELECT * /*This is the outer query part */
FROM Employee Emp1
WHERE (N-1) = ( /* Subquery starts here */
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)

Lo más importante a entender en la consulta anterior es que la subconsulta se evalúa cada vez que una fila es procesada por la consulta externa. En otras palabras, la consulta interna no se puede procesar independientemente de la consulta externa ya que la consulta interna utiliza el valor Emp1 como bien.

Para encontrar el enésimo salario más alto, solo encontramos el salario que tiene exactamente N-1 salarios mayores que sí mismo.


Solución 2: Encuentre el enésimo salario más alto usando la palabra clave SUPERIOR en SQL Server

SELECT TOP 1 Salary
FROM (
      SELECT DISTINCT TOP N Salary
      FROM Employee
      ORDER BY Salary DESC
      ) AS Emp
ORDER BY Salary

Solución 3: Encuentre el enésimo salario más alto en SQL Server sin usar TOP

SELECT Salary FROM Employee 
ORDER BY Salary DESC OFFSET N-1 ROW(S) 
FETCH FIRST ROW ONLY

Tenga en cuenta que no he probado personalmente el SQL anterior, y creo que solo funcionará en SQL Server 2012 y arriba.

 1
Author: Zinan Xing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-05 18:49:41

El método más fácil es obtener 2nd higest salary de table en SQL:

sql> select max(sal) from emp where sal not in (select max(sal) from emp);
 0
Author: Sonu Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-19 05:57:16
SELECT * FROM 
(select distinct postalcode  from Customers order by postalcode DESC)
limit 4,1;

4 aquí significa dejar los primeros 4 y mostrar el siguiente 1.

Prueba esto funciona para mí.

 0
Author: Saif Grover,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-07 15:11:26

Una consulta muy simple para encontrar el enésimo salario más alto

SELECT DISTINCT(Sal) FROM emp ORDER BY Salary DESC LIMIT n,1
 -3
Author: deepakjoshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-05 06:38:45