Pregunta Cómo obtener el segundo mejor salario en una mesa


Es una pregunta que tengo esta tarde:

Allí, una tabla contiene ID, Nombre y Salario de empleados, obtener nombres de los empleados con el segundo salario más alto, en SQL Server

Aquí está mi respuesta, lo acabo de escribir en papel y no estoy seguro de que sea perfectamente válido, pero parece funcionar:

SELECT Name FROM Employees WHERE Salary = 
( SELECT DISTINCT TOP (1) Salary FROM Employees WHERE Salary NOT IN
 (SELECT DISTINCT TOP (1) Salary FROM Employees ORDER BY Salary DESCENDING)
ORDER BY Salary DESCENDING)

Creo que es feo, pero es la única solución que se me viene a la mente.

¿Me puede sugerir una mejor consulta?

Muchas gracias.


32
2017-09-14 13:48


origen


Respuestas:


Para obtener los nombres de los empleados con el segundo monto salarial distinto más alto que puede usar.

;WITH T AS
(
SELECT *,
       DENSE_RANK() OVER (ORDER BY Salary Desc) AS Rnk
FROM Employees
)
SELECT Name
FROM T
WHERE Rnk=2;

Si el salario se indexa, lo siguiente puede ser más eficiente, especialmente si hay muchos empleados.

SELECT Name
FROM   Employees
WHERE  Salary = (SELECT MIN(Salary)
                 FROM   (SELECT DISTINCT TOP (2) Salary
                         FROM   Employees
                         ORDER  BY Salary DESC) T);

Script de prueba

CREATE TABLE Employees
  (
     Name   VARCHAR(50),
     Salary FLOAT
  )

INSERT INTO Employees
SELECT TOP 1000000 s1.name,
                   abs(checksum(newid()))
FROM   sysobjects s1,
       sysobjects s2

CREATE NONCLUSTERED INDEX ix
  ON Employees(Salary)

SELECT Name
FROM   Employees
WHERE  Salary = (SELECT MIN(Salary)
                 FROM   (SELECT DISTINCT TOP (2) Salary
                         FROM   Employees
                         ORDER  BY Salary DESC) T);

WITH T
     AS (SELECT *,
                DENSE_RANK() OVER (ORDER BY Salary DESC) AS Rnk
         FROM   Employees)
SELECT Name
FROM   T
WHERE  Rnk = 2;

SELECT Name
FROM   Employees
WHERE  Salary = (SELECT DISTINCT TOP (1) Salary
                 FROM   Employees
                 WHERE  Salary NOT IN (SELECT DISTINCT TOP (1) Salary
                                       FROM   Employees
                                       ORDER  BY Salary DESC)
                 ORDER  BY Salary DESC)

SELECT Name
FROM   Employees
WHERE  Salary = (SELECT TOP 1 Salary
                 FROM   (SELECT TOP 2 Salary
                         FROM   Employees
                         ORDER  BY Salary DESC) sel
                 ORDER  BY Salary ASC)  

28
2017-09-14 13:52



SELECCIONAR * del empleado
DÓNDE Salario IN (SELECCIONE MAX (Salario)
                 DESDE Empleado
                 DÓNDE Salario NO EN (SELECCIONE MAX (Salario)
                                      Empleado de FFROM));

Intenta así ..


31
2017-08-08 20:19



Esto podría ayudarte

SELECT MIN(SALARY) FROM EMP WHERE SALARY in (SELECT DISTINCT TOP 2 SALARY FROM EMP ORDER BY SALARY DESC)

podemos encontrar cualquier nth salario más alto poniendo 'n' (n > 0) en lugar de '2'

ejemplo para el quinto salario más alto que ponemos n = 5


8
2018-02-13 05:54



¿Qué tal un CTE?

;WITH Salaries AS
(
    SELECT Name, Salary,
       DENSE_RANK() OVER(ORDER BY Salary DESC) AS 'SalaryRank'
    FROM 
        dbo.Employees
)
SELECT Name, Salary
FROM Salaries  
WHERE SalaryRank = 2

DENSE_RANK() le dará a todos los empleados que tienen el segundo salario más alto, sin importar cuántos empleados tengan el salario más alto (idéntico).


7
2017-09-14 13:52



Otra forma intuitiva es: Supongamos que queremos encontrar el N-ésimo salario más alto

1) Clasificar Empleado según el orden descendente de salario

2) Tome los primeros N registros usando rownum. Entonces, en este paso, el n. ° registro aquí es el N-ésimo salario más alto

3) Ahora ordena este resultado temporal en orden ascendente. Así, el N-ésimo salario más alto es ahora el primer registro

4) Obtenga el primer registro de este resultado temporal.

Será el N-ésimo salario más alto.

select * from 
 (select * from 
   (select * from  
       (select * from emp order by sal desc)  
   where rownum<=:N )  
 order by sal )
where rownum=1;

En caso de que haya sueldos que se repiten, en la consulta más interna se puede usar distinto.

select * from 
 (select * from 
   (select * from  
       (select distinct(sal) from emp order by 1 desc)  
   where rownum<=:N )  
 order by sal )
where rownum=1;

5
2018-02-01 06:01



Manera simple SIN usar ninguna característica especial específica de Oracle, MySQL, etc.

Supongamos que la tabla EMPLOYEE tiene datos como a continuación. Los sueldos se pueden repetir. enter image description here

Por análisis manual podemos decidir los rangos de la siguiente manera:
enter image description here

El mismo resultado se puede lograr mediante 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
order by rank

enter image description here

Primero descubrimos salarios distintos. Luego descubrimos el recuento de salarios distintos superiores a cada fila. Esto no es más que el rango de esa identificación. Para el salario más alto, este conteo será cero. Entonces '+1' se hace para comenzar el rango desde 1.

Ahora podemos obtener identificaciones en el N ° rango agregando la cláusula where a la consulta anterior.

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;

3
2017-11-16 05:22



select MAX(Salary) from Employee WHERE Salary NOT IN (select MAX(Salary) from Employee );

3
2017-11-14 13:59



Creo que querrías usar DENSE_RANK ya que no sabe cuántos empleados tienen el mismo salario y dijo que quería nombres de empleados.

CREATE TABLE #Test
(
    Id INT,
    Name NVARCHAR(12),
    Salary MONEY
)

SELECT x.Name, x.Salary
FROM
        (
        SELECT  Name, Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) as Rnk
        FROM    #Test
        ) x
WHERE x.Rnk = 2

ROW_NUMBER le daría una numeración única, incluso si los salarios están vinculados, y simple RANK no le daría un '2' como rango si tuviera varias personas empatando por el salario más alto. He corregido esto como DENSE_RANK hace el mejor trabajo para esto


2
2017-09-14 13:56



Debajo de la consulta puede usarse para encontrar el enésimo valor máximo, simplemente reemplace 2 del enésimo número

select * from emp e1 where 2 =(select count(distinct(salary)) from emp e2
   where e2.emp >= e1.emp)

2
2017-09-14 14:53



select * from emp where salary = (  
    select salary from   
       (select ROW_NUMBER() over (order by salary) as 'rownum', *
        from emp) t -- Order employees according to salary  
    where rownum = 2 -- Get the second highest salary
)

1
2017-09-14 13:59