Write a SQL query to get the second highest salary from the Employee table.
| Id | Salary |
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
<
Query:
CREATE TABLE a
([Id] int, [Salary] int)
;
INSERT INTO a
([Id], [Salary])
VALUES
(1, 100),
(2, 200),
(3, 300)
;
GO
SELECT Salary as SecondHighestSalary
FROM a
ORDER BY Salary
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
| SecondHighestSalary |
| ------------------: |
| 200 |
You can use RANK() function to rank the values for Salary column.
SELECT *
FROM
(
SELECT *, RANK()OVER(ORDER BY Salary DESC) As SalaryRank
FROM Employee
) AS Tab
WHERE SalaryRank = 2
You can try this for getting n-th highest salary, where n = 1,2,3....(int)
SELECT TOP 1 salary FROM (
SELECT TOP n salary
FROM employees
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
Hope this will help you. Below is one of the implementation.
create table #salary (salary int)
insert into #salary values (100), (200), (300)
SELECT TOP 1 salary FROM (
SELECT TOP 2 salary
FROM #salary
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
drop table #salary
The output is here 200 as 300 is first highest, 200 is second highest and 100 is the third highest as shown below
salary
200
Here n is 2
While you can use a CTE (from MSSQL 2005 or newer) or ROWNUMBER the easiest and more "portable" way is to just order by twice using a subquery.
select top 1 x.* from
(select top 2 t1.* from dbo.Employee t1 order by t1.Salary) as x
order by x.Salary desc
The requisite to show null when there's not a second bigger salary is a bit more tricky but also easy to do with a if.
if (select count(*) from dbo.Employee) > 1
begin
select top 1 x.* from
(select top 2 emp.* from dbo.Employee emp order by emp.Salary) as x
order by x.Salary desc
end
else begin
select null as Id, null as Salary
end
Obs:. OP don't said what to do when the second largest is a tie with the first but using this solution is a simple matter of using a DISTINCT in the IF subquery.
I would use DENSE_RANK()
& do LEFT JOIN
with employee table :
SELECT t.Seq, e.*
FROM ( VALUES (2)
) t (Seq) LEFT JOIN
(SELECT e.*,
DENSE_RANK() OVER (ORDER BY Salary DESC) AS Num
FROM Employee e
) e
ON e.Num = t.Seq;
In case of ties you want the second highest distinct value. E.g. for values 100, 200, 300, 300, you want 200.
So get the highest value (MAX(salary)
=> 300) and then get the highest value less than that:
select max(salary) from mytable where salary < (select max(salary) from mytable);