It\'s a question I got this afternoon:
There a table contains ID, Name, and Salary of Employees, get names of the second-highest salary employees, in SQL Server
I think you would want to use DENSE_RANK
as you don't know how many employees have the same salary and you did say you wanted nameS of employees.
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
would give you unique numbering even if the salaries tied, and plain RANK
would not give you a '2' as a rank if you had multiple people tying for highest salary. I've corrected this as DENSE_RANK
does the best job for this.
Try this to get the respective nth highest salary.
SELECT
*
FROM
emp e1
WHERE
2 = (
SELECT
COUNT(salary)
FROM
emp e2
WHERE
e2.salary >= e1.salary
)
Simple way WITHOUT using any special feature specific to Oracle, MySQL etc.
Suppose EMPLOYEE table has data as below. Salaries can be repeated.
By manual analysis we can decide ranks as follows :-
Same result can be achieved by query
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
First we find out distinct salaries. Then we find out count of distinct salaries greater than each row. This is nothing but the rank of that id. For highest salary, this count will be zero. So '+1' is done to start rank from 1.
Now we can get IDs at Nth rank by adding where clause to above query.
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;
declare
cntr number :=0;
cursor c1 is
select salary from employees order by salary desc;
z c1%rowtype;
begin
open c1;
fetch c1 into z;
while (c1%found) and (cntr <= 1) loop
cntr := cntr + 1;
fetch c1 into z;
dbms_output.put_line(z.salary);
end loop;
end;
Try this: This will give dynamic results irrespective of no of rows
SELECT * FROM emp WHERE salary = (SELECT max(e1.salary)
FROM emp e1 WHERE e1.salary < (SELECT Max(e2.salary) FROM emp e2))**
Creating temporary table
Create Table #Employee (Id int identity(1,1), Name varchar(500), Salary int)
Insert data
Insert Into #Employee
Select 'Abul', 5000
Union ALL
Select 'Babul', 6000
Union ALL
Select 'Kabul', 7000
Union ALL
Select 'Ibul', 8000
Union ALL
Select 'Dabul', 9000
Query will be
select top 1 * from #Employee a
Where a.id <> (Select top 1 b.id from #Employee b ORDER BY b.Salary desc)
order by a.Salary desc
Drop table
drop table #Empoyee