Finding the second-highest salary in SQL can be done in a few different ways, depending on the database and the scenario.
The most straightforward and widely used method is with the ORDER BY and OFFSET/FETCH or LIMIT clause. For example:
SELECT Salary
FROM Employees
ORDER BY Salary DESC
OFFSET 1 ROW FETCH NEXT 1 ROW ONLY;
This skips the first (highest) salary and fetches the next one β the second-highest.
But since not all databases support OFFSET or FETCH, a more traditional way is using a subquery:
SELECT MAX(Salary) AS SecondHighestSalary
FROM Employees
WHERE Salary < (SELECT MAX(Salary) FROM Employees);
Here, the inner query finds the highest salary, and the outer query looks for the maximum salary less than that β effectively giving the second-highest salary.
I applied this logic in a performance appraisal report where we needed to identify the top two earners in each department. I used a similar subquery within a PARTITION BY DepartmentID using window functions:
SELECT EmployeeID, Salary
FROM (
SELECT EmployeeID, Salary,
DENSE_RANK() OVER (ORDER BY Salary DESC) AS rnk
FROM Employees
) AS ranked
WHERE rnk = 2;
This approach works well when you want the second-highest salary per department or group, not just overall.
One challenge I faced was when multiple employees had the same top salary. In that case, using RANK() instead of ROW_NUMBER() was important, because RANK() properly handles ties β otherwise, the second-highest might get skipped.
A limitation is that performance can drop if the table is very large and thereβs no index on the Salary column.
An alternative for older databases without window functions is to use the TOP or LIMIT approach:
SELECT Salary
FROM Employees
ORDER BY Salary DESC
LIMIT 1 OFFSET 1;
So overall, the best method depends on the SQL dialect β but conceptually, itβs always about skipping the highest and retrieving the next unique value.
