Selecting the record(s) with the "second" highest something - sql

I have written the following SQL commands for retrieving data from a table called Employee.
I was able to get the highest/maximum salary as well as the second highest/maximum salary, but I am having difficulty writing the same when the whole record needs to be returned.
Select all the employees.
SELECT * FROM Employee
Return the highest salary. This returns the maximum salary amount which is 90000
SELECT MAX(salary) FROM Employee
Return the employee record with the highest salary. This returns all the records of the person/people with their salary being the maximum salary which is 90000 that is only John Henry in this case.
SELECT *
FROM Employee
WHERE salary = ( SELECT MAX(salary) FROM Employee )
Return every other employee record; i.e. everyone except the one with the highest salary.
SELECT *
FROM Employee
WHERE salary != ( SELECT MAX(salary) FROM Employee )
Return the second highest salary. This returns the second maximum salary amount which is 85000
SELECT MAX(salary) FROM Employee
WHERE salary != ( SELECT MAX(salary) FROM Employee )
Return the employee record with the second highest salary. This returns all the records of the person/people with their salary being the second maximum salary which is 85000 that is only Michael Greenback in this case.
I am stuck in this... I tried using HAVING as an extra condition, but however I arrange it to specify a condition, I get syntax errors. How do I do this?

Window functions are the built-in functionality to do this. In particular, dense_rank():
select e.*
from (select e.*, dense_rank() over (order by salary desc) as seqnum
from employee e
) e
where seqnum = 2;

This is a SQL Server solution but can be easily re-written using limit N instead of top N. If your database doesn't support window functions, you could try this. If it does, Gordon's solution is the way to go.
with cte as
(select max(salary) as second_max
from employee
where salary in (select distinct top 2 salary -- top n is what makes this scalable
from employee
order by salary asc)) -- get top 2 salaries and sort them
select *
from employee
where salary = (select second_max from cte);

Related

SQL Query with two WHERE conditions

My task is:
To make a query which will get Employees, who earn the biggest salary for their working experience. In other words, the Employee who earns the biggest salary with the biggest experience.
As I consider, I need to make a query with two conditions:
select * from employee where salary in (select max(salary) from employee) and
hire_date in (select min(hire_date) from employee)
I think this was what you're trying to do:
select * from (
select *,
datediff(day,hire_date,getdate()) [Days_Worked],
dense_Rank() over(Partition by datediff(day,hire_date,getdate()) order by salary desc) [RN]
from employee
)a
where a.RN = 1
order by Days_Worked DESC
So that'll give you a list of employees with the highest salary against the employees that have worked the same number of days.
Just note that with dense rank if for example there are 2 employees that have worked 88 days and both earn $50000 (higher than anyone else) it will list both employees, use ROW_NUMBER() instead of DENSE_RANK() if you want to restrict examples like that to 1 employee.
If I get it correctly, this query solves your problem.
SELECT TOP 1 WITH TIES * FROM
employee
ORDER BY
hire_date ASC,
salary DESC

Employee that has a higher salary than the AVERAGE of his department - optimized

We have only a table named EMPLOYEESALARY in our database with the 3 following columns:
Employee_ID, Employee_Salary, Department_ID
Now I have to SELECT every employee that has a higher salary than the AVERAGE of his department. How do I do that?
I know this is a repeat question but the best solution I found everywere was:
SELECT * from employee join (SELECT AVG(employee_salary) as sal, department_ID
FROM employee GROUP BY Department_ID) as t1
ON employee.department_ID = t1.department_ID
where employee.employee_salary > t1.sal
Can we optimize it further and do it without a subquery?
Reference:
SELECT every employee that has a higher salary than the AVERAGE of his department
Employees with higher salary than their department average?
Find Schema here, to test: SQL Fiddle
Can we do it without a subquery?
Not that I can think of. Had the condition been >= then the following would have worked
SELECT TOP 1 WITH TIES *
FROM employee
ORDER BY CASE
WHEN employee_salary >= AVG(employee_salary)
OVER (
PARTITION BY Department_ID) THEN 0
ELSE 1
END
But this is not an optimisation and it won't work correctly for the > condition if no employee has a salary greater than the average anyway (i.e. all employees in a department had the same salary)
Can we optimize it further?
You could shorten the syntax a bit with
WITH T AS
(
SELECT *,
AVG(employee_salary) OVER (PARTITION BY Department_ID) AS sal
FROM employee
)
SELECT *
FROM T
WHERE employee_salary > sal
but it still has to do much the same work.
Assuming suitable indexes on the base table already exist then the only way of avoiding some more of that work at SELECT time would be to pre-calculate the grouped SUM and COUNT_BIG in an indexed view grouped by Department_ID (to allow the average to be cheaply derived) .
A more optimal form is likely to be:
select e.*
from (select e.*, avg(employee_salary) over (partition by department_id) as avgs
from employee e
) e
where employee_salary > avgs;
This (as well as other versions) can use an index on employee(department_id, employee_salary). The final where probably should not use an index, because it is selecting lots of rows.

SQL query to find third highest salary in company

I need to write a query that will return the third highest salaried employee in the company.
I was trying to accomplish this with subqueries, but could not get the answer. My attempts are below:
select Max(salary)
from employees
where Salary not in
(select Max(salary)
from employees
where Salary not in
(select Max(salary)
from employees));
My thought was that I could use 2 subqueries to elimitate the first and second highest salaries. Then I could simply select the MAX() salary that is remaining. Is this a good option, or is there a better way to achieve this?
The most simple way that should work in any database is to do following:
SELECT * FROM `employee` ORDER BY `salary` DESC LIMIT 1 OFFSET 2;
Which orders employees by salary and then tells db to return a single result (1 in LIMIT) counting from third row in result set (2 in OFFSET). It may be OFFSET 3 if your DB counts result rows from 1 and not from 0.
This example should work in MySQL and PostgreSQL.
Edit:
But there's a catch if you only want the 3rd highest DISTINCT salary. Than you should add the DISTINCT keyword.
In case of salary list: 100, 90, 90, 80, 70.
In the above query it will produce the 3rd highest salary which is 90. But if you mean the 3rd distinct which is 80 than you should use
SELECT DISTINCT `salary` FROM `employee` ORDER BY `salary` DESC LIMIT 1 OFFSET 2;
But there's a catch, this will return you only 1 column which is Salary, because in order to operate the distinction operation, DISTINCT can only operate on a specific set of columns.
This means we should add another wrapping query to extract the employees(There can be multiple) that matches that result. Thus I added LIMIT 1 at the end.
SELECT *
FROM `employee`
WHERE
`Salary` = (SELECT DISTINCT `Salary`
FROM `employee`
ORDER BY `salary` DESC
LIMIT 1 OFFSET 2
)
LIMIT 1;
Examples can be found HERE
You can get the third highest salary by using limit , by using TOP keyword and sub-query
TOP keyword
SELECT TOP 1 salary
FROM
(SELECT TOP 3 salary
FROM Table_Name
ORDER BY salary DESC) AS Comp
ORDER BY salary ASC
limit
SELECT salary
FROM Table_Name
ORDER BY salary DESC
LIMIT 2, 1
by subquery
SELECT salary
FROM
(SELECT salary
FROM Table_Name
ORDER BY salary DESC
LIMIT 3) AS Comp
ORDER BY salary
LIMIT 1;
I think anyone of these help you.
You may try (if MySQL):
SELECT salary FROM employee ORDER BY salary DESC LIMIT 2, 1;
This query returns one row after skipping two rows.
You may also want to return distinct salary. For example, if you have 20,20,10 and 5 then 5 is the third highest salary. To do so, add DISTINCT to the above query:
SELECT DISTINCT salary FROM employee ORDER BY salary DESC LIMIT 2, 1;
SELECT Max(salary)
FROM employee
WHERE salary < (SELECT Max(salary)
FROM employee
WHERE salary NOT IN(SELECT Max(salary)
FROM employee))
hope this helped you
If SQL Server this could work
SELECT TOP (1) * FROM
(SELECT TOP (3) salary FROM employees ORDER BY salary DESC) T
ORDER BY salary ASC
As for your number of subqueries question goes it depends on your language. Check this for more information
Is there a nesting limit for correlated subqueries in Oracle?
SELECT id
FROM tablename
ORDER BY id DESC
LIMIT 2 , 1
This is only for get 3rd highest value .
You may use this for all employee with 3rd highest salary:
SELECT * FROM `employee` WHERE salary = (
SELECT DISTINCT(`salary`) FROM `employee` ORDER BY `salary` DESC LIMIT 1 OFFSET 2
);
Some DBMS's don't allow you to run several nested queries. Here is a solution that only uses 1 nested query:
SELECT salary
FROM
(
SELECT salary
FROM employees
ORDER BY salary
LIMIT 3
) as TBL1
ORDER BY salary DESC
LIMIT 1;
It should give you the desired result. It first finds the 3 largest salaries, then selects the smallest of the three (or the third one if they are equal). Here is an SQLFiddle
I found a very good explanation in
http://www.programmerinterview.com/index.php/database-sql/find-nth-highest-salary-sql/
This query should give nth highest salary
SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
SELECT MAX(salary) FROM employees GROUP BY salary ORDER BY salary DESC LIMIT 1 OFFSET 2;
SELECT * FROM employee ORDER BY salary DESC LIMIT 1 OFFSET 2;
You can use nested query to get that, like below one is explained for the third max salary. Every nested salary is giving you the highest one with the filtered where result and at the end it will return you exact 3rd highest salary irrespective of number of records for the same salary.
select * from users where salary < (select max(salary) from users where salary < (select max(salary) from users)) order by salary desc limit 1
Below query will give accurate answer. Follow and give me comments:
select top 1 salary from (
select DISTINCT top 3 salary from Table(table name) order by salary ) as comp
order by personid salary
you can get any order for salary with that:
select * from
(
select salary,row_Number() over (order by salary DESC ) RN
FROM employees
)s
where RN = 3
-- put RN equal to any number of orders.
--for your question put 3
You can find Nth highest salary by making use of just one single query which is very simple to understand:-
select salary from employees e1 where N-1=(select count(distinct
salary) from employees e2 where e2.salary>e1.salary);
Here Replace "N" with number(1,2,3,4,5...).This query work properly even when where salaries are duplicate. The simple idea behind this query is that the inner subquery
count how many salaries are greater then (N-1). When we get the count then the cursor will point to that row which is N and it simply returns the salary present in that row.
SELECT salary FROM employees e1
WHERE N-1 = (SELECT COUNT(DISTINCT salary) FROM employees e2
WHERE e2.salary > e1.salary)
Here, I have solved it with a correlated nested query. It is a generalized Query so if you want to print 4th, 5th, or any number of highest salary it will work perfectly even if there are any duplicate salaries.
So, what you have to do is simply change the N value here. So, in your case, it will be,
SELECT salary FROM employees e1
WHERE 3-1 = (SELECT COUNT(DISTINCT salary) FROM employees e2
WHERE e2.salary > e1.salary)
Note that the third highest salary may be the same the the first highest salary so your current approach wouldn't work.
I would do order the employees by salary and apply a LIMIT 3 at the end of the SQL query. You'll then have the top three of highest salaries and, thus, you also have the third highest salary (if there is one, a company may have two employees and then you wouldn't have a third highest salary).
For me this query work fine in Mysql
it will return third max salary from table
SELECT salary FROM users ORDER BY salary DESC LIMIT 1 OFFSET 2;
or
SELECT salary FROM users ORDER BY salary DESC LIMIT 2,1;
select min (salary) from Employee where Salary in (Select Top 3 Salary from Employee order by Salary desc)
SELECT TOP 1 BILL_AMT Bill_Amt FROM ( SELECT DISTINCT TOP 3 NH_BL_BILL.BILL_AMT FROM NH_BL_BILL ORDER BY BILL_AMT DESC) A
ORDER BY BILL_AMT ASC
SELECT DISTINCT MAX(salary) AS max
FROM STAFF
WHERE salary IN
(SELECT salary
FROM STAFF
WHERE salary<(SELECT MAX(salary) AS maxima
FROM STAFF
WHERE salary<
(SELECT MAX(salary) AS maxima
FROM STAFF))
GROUP BY salary);
I have tried other ways they are not right. This one works.
We can find the Top nth Salary with this Query.
WITH EMPCTE AS (
SELECT E.*, DENSE_RANK() OVER(ORDER BY SALARY DESC) AS DENSERANK
FROM EMPLOYEES E
)
SELECT * FROM EMPCTE WHERE DENSERANK=&NUM
for oracle it goes like this:
select salary from employee where rownnum<=3 order by salary desc
minus
select salary from employee where rownnum<=2 order by salary desc;
The SQL-Server implementation of this will be:
SELECT SALARY FROM EMPLOYEES OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY
This is a MYSQL query.
Explanation: The subquery returns top 3 salaries. From the returned result, we select the minimum salary, which is the 3rd highest salary.
SELECT MIN(Salary)
FROM (
SELECT Salary
FROM Employees
ORDER BY Salary DESC
LIMIT 3
) AS TopThreeSalary;
in Sql Query you can get nth highest salary
select * from(
select empname, sal, dense_rank()
over(order by sal desc)r from Employee)
where r=&n;
To find to the 2nd highest sal set n = 2
To find 3rd highest sal set n = 3 and so on.
This works fine with Oracle db.
select SAL from ( SELECT DISTINCT SAL FROM EMP ORDER BY SAL DESC FETCH FIRST 3 ROWS ONLY ) ORDER BY SAL ASC FETCH FIRST 1 ROWS ONLY
SELECT *
FROM maintable_B7E8K
order by Salary
desc limit 1 offset 2;
--Oracle SQL
with temp as (
select distinct salary from HR.EMPLOYEES
order by SALARY desc
)
select min(temp.salary) from temp
where rownum <= 3;
SELECT * FROM(
SELECT salary, DENSE_RANK()
OVER(ORDER BY salary DESC)r FROM Employee)
WHERE r=&n;
To find the 3rd highest salary set n = 3

How to get second-highest salary employees in a table

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
Here's my answer, I just wrote it in paper and not sure that it's perfectly valid, but it seems to work:
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)
I think it's ugly, but it's the only solution come to my mind.
Can you suggest me a better query?
Thank you very much.
To get the names of the employees with the 2nd highest distinct salary amount you can use.
;WITH T AS
(
SELECT *,
DENSE_RANK() OVER (ORDER BY Salary Desc) AS Rnk
FROM Employees
)
SELECT Name
FROM T
WHERE Rnk=2;
If Salary is indexed the following may well be more efficient though especially if there are many employees.
SELECT Name
FROM Employees
WHERE Salary = (SELECT MIN(Salary)
FROM (SELECT DISTINCT TOP (2) Salary
FROM Employees
ORDER BY Salary DESC) T);
Test Script
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)
SELECT * from Employee
WHERE Salary IN (SELECT MAX(Salary)
FROM Employee
WHERE Salary NOT IN (SELECT MAX(Salary)
FFROM employee));
Try like this..
This might help you
SELECT
MIN(SALARY)
FROM
EMP
WHERE
SALARY in (SELECT
DISTINCT TOP 2 SALARY
FROM
EMP
ORDER BY
SALARY DESC
)
We can find any nth highest salary by putting n (where n > 0) in place of 2
Example for 5th highest salary we put n = 5
How about a 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() will give you all the employees who have the second highest salary - no matter how many employees have the (identical) highest salary.
All of the following queries work for MySQL:
SELECT MAX(salary) FROM Employee WHERE Salary NOT IN (SELECT Max(Salary) FROM Employee);
SELECT MAX(Salary) From Employee WHERE Salary < (SELECT Max(Salary) FROM Employee);
SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1;
SELECT Salary FROM (SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT 2) AS Emp ORDER BY Salary LIMIT 1;
Another intuitive way is :-
Suppose we want to find Nth highest salary then
1) Sort Employee as per descending order of salary
2) Take first N records using rownum. So in this step Nth record here is Nth highest salary
3) Now sort this temporary result in ascending order. Thus Nth highest salary is now first record
4) Get first record from this temporary result.
It will be Nth highest salary.
select * from
(select * from
(select * from
(select * from emp order by sal desc)
where rownum<=:N )
order by sal )
where rownum=1;
In case there are repeating salaries then in innermost query distinct can be used.
select * from
(select * from
(select * from
(select distinct(sal) from emp order by 1 desc)
where rownum<=:N )
order by sal )
where rownum=1;
select MAX(Salary) from Employee WHERE Salary NOT IN (select MAX(Salary) from Employee );
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;
The simple way is to use OFFSET. Not only second, any position we can query using offset.
SELECT SALARY,NAME FROM EMPLOYEE ORDER BY SALARY DESC LIMIT 1 OFFSET 1 --Second largest
SELECT SALARY,NAME FROM EMPLOYEE ORDER BY SALARY DESC LIMIT 1 OFFSET 9 --For 10th largest
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.
Below query can be used to find the nth maximum value, just replace 2 from nth number
select * from emp e1 where 2 =(select count(distinct(salary)) from emp e2
where e2.emp >= e1.emp)
Here I used two queries for the following scenarios which are asked during an interview
First scenario:
Find all second highest salary in the table (Second highest salary with more than
one employee )
select * from emp where salary
In (select MAX(salary) from emp where salary NOT IN (Select MAX(salary) from
emp));
Second scenario:
Find only the second highest salary in the table
select min(temp.salary) from (select * from emp order by salary desc limit 2)
temp;
There are two way to do this first:
Use subquery to find the 2nd highest
SELECT MAX(salary) FROM employees
WHERE salary NOT IN (
SELECT MAX (salary) FROM employees)
But this solution is not much good as if you need to find out the 10 or 100th highest then you may be in trouble. So instead go for window function like
select * from
(
select salary,ROW_NUMBER() over(
order by Salary desc) as
rownum from employees
) as t where t.rownum=2
By using this method you can find out nth highest salary without any trouble.
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
)
select max(age) from yd where age<(select max(age) from HK) ; /// True two table Highest
SELECT * FROM HK E1 WHERE 1 =(SELECT COUNT(DISTINCT age) FROM HK E2 WHERE E1.age < E2.age); ///Second Hightest age RT single table
select age from hk e1 where (3-1) = (select count(distinct (e2.age)) from yd e2 where e2.age>e1.age);//// same True Second Hight age RT two table
select max(age) from YD where age not in (select max(age) from YD); //second hight age in single table
Can we also use
select e2.max(sal), e2.name
from emp e2
where (e2.sal <(Select max (Salary) from empo el))
group by e2.name
Please let me know what is wrong with this approach
SELECT *
FROM TABLE1 AS A
WHERE NTH HIGHEST NO.(SELECT COUNT(ATTRIBUTE) FROM TABLE1 AS B) WHERE B.ATTRIBUTE=A.ATTRIBUTE;
this is the simple query .. if u want the second minimum then just change the max to min and change the less than(<) sign to grater than(>).
select max(column_name) from table_name where column_name<(select max(column_name) from table_name)
SELECT name
FROM employee
WHERE salary =
(SELECT MIN(salary)
FROM (SELECT TOP (2) salary
FROM employee
ORDER BY salary DESC) )
SELECT MAX(Salary) FROM Employee
WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee)
If you want to display the name of the employee who is getting the second highest salary then use this:
SELECT employee_name
FROM employee
WHERE salary = (SELECT max(salary)
FROM employee
WHERE salary < (SELECT max(salary)
FROM employee);
Try This one
select * from
(
select name,salary,ROW_NUMBER() over( order by Salary desc) as
rownum from employee
) as t where t.rownum=2
http://askme.indianyouth.info/details/write-a-sql-query-to-find-the-10th-highest-employee-salary-from-an-employee-table-explain-your-answer-111
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
)
Select * from employee where salary = (Select max(salary) from employee where salary not in(Select max(salary)from employee))
Explanation :
Query 1 : Select max(salary) from employee where salary not in(Select max(salary) from employee) - This query will retrieve second highest salary
Query 2 : Select * from employee where salary=(Query 1) - This query will retrieve all the records having second highest salary(Second highest salary may have multiple records)
I think this is probably the simplest out of the lot.
SELECT Name FROM Employees group BY Salary DESCENDING limit 2;
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))**
Here's a simple approach:
select name
from employee
where salary=(select max(salary)
from(select salary from employee
minus
select max(salary) from employee));
I want to post here possibly easiest solution. It worked in mysql.
Please check at your end too:
SELECT name
FROM `emp`
WHERE salary = (
SELECT salary
FROM emp e
ORDER BY salary DESC
LIMIT 1
OFFSET 1
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;
Using this SQL, Second highest salary will get with Employee Name
Select top 1 start at 2 salary from employee group by salary order by salary desc;

SQL query to find Nth highest salary from a salary table

How can I find the Nth highest salary in a table containing salaries in SQL Server?
You can use a Common Table Expression (CTE) to derive the answer.
Let's say you have the following salaries in the table Salaries:
EmployeeID Salary
--------------------
10101 50,000
90140 35,000
90151 72,000
18010 39,000
92389 80,000
We will use:
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
This will create a row number for each row after it has been sorted by the Salary in descending order, then retrieve the third row (which contains the third-highest record).
SQL Fiddle
For those of you who don't want a CTE (or are stuck in SQL 2000):
[Note: this performs noticably worse than the above example; running them side-by-side with an exceution plans shows a query cost of 36% for the CTE and 64% for the subquery]:
SELECT TOP 1 Salary
FROM
(
SELECT TOP N Salary
FROM Salaries
ORDER BY Salary DESC
) SalarySubquery
ORDER BY Salary ASC
where N is defined by you.
SalarySubquery is the alias I have given to the subquery, or the query that is in parentheses.
What the subquery does is it selects the top N salaries (we'll say 3 in this case), and orders them by the greatest salary.
If we want to see the third-highest salary, the subquery would return:
Salary
-----------
80,000
72,000
50,000
The outer query then selects the first salary from the subquery, except we're sorting it ascending this time, which sorts from smallest to largest, so 50,000 would be the first record sorted ascending.
As you can see, 50,000 is indeed the third-highest salary in the example.
You could use row_number to pick a specific row. For example, the 42nd highest salary:
select *
from (
select row_number() over (order by Salary desc) as rn
, *
from YourTable
) as Subquery
where rn = 42
Windowed functions like row_number can only appear in select or order by clauses. The workaround is placing the row_number in a subquery.
select MIN(salary) from (
select top 5 salary from employees order by salary desc) x
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
)
Suppose you want to find 5th highest salary, which means there are total 4 employees who have salary greater than 5th highest employee. So for each row from the outer query check the total number of salaries which are greater than current salary. Outer query will work for 100 first and check for number of salaries greater than 100. It will be 6, do not match (5-1) = 6 where clause of outerquery. Then for 800, and check for number of salaries greater than 800, 4=0 false then work for 300 and finally there are totally 4 records in the table which are greater than 300. Therefore 4=4 will meet the where clause and will return
3 C 300.
try it...
use table_name
select MAX(salary)
from emp_salary
WHERE marks NOT IN (select MAX(marks)
from student_marks )
Simple way WITHOUT using any special feature specific to Oracle, MySQL etc.
Suppose in EMPLOYEE table Salaries can be repeated.
Use query to find out rank of each 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
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;
The easiest method is to get 2nd higest salary from table in SQL:
sql> select max(sal) from emp where sal not in (select max(sal) from emp);
Dont forget to use the distinct keyword:-
SELECT TOP 1 Salary
FROM
(
SELECT Distinct TOP N Salary
FROM Salaries
ORDER BY Salary DESC
) SalarySubquery
ORDER BY Salary ASC
Solution 1: This SQL to find the Nth highest salary should work in SQL Server, MySQL, DB2, Oracle, Teradata, and almost any other RDBMS: (note: low performance because of subquery)
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)
The most important thing to understand in the query above is that the subquery is evaluated each and every time a row is processed by the outer query. In other words, the inner query can not be processed independently of the outer query since the inner query uses the Emp1 value as well.
In order to find the Nth highest salary, we just find the salary that has exactly N-1 salaries greater than itself.
Solution 2: Find the nth highest salary using the TOP keyword in SQL Server
SELECT TOP 1 Salary
FROM (
SELECT DISTINCT TOP N Salary
FROM Employee
ORDER BY Salary DESC
) AS Emp
ORDER BY Salary
Solution 3: Find the nth highest salary in SQL Server without using TOP
SELECT Salary FROM Employee
ORDER BY Salary DESC OFFSET N-1 ROW(S)
FETCH FIRST ROW ONLY
Note that I haven’t personally tested the SQL above, and I believe that it will only work in SQL Server 2012 and up.
SELECT * FROM
(select distinct postalcode from Customers order by postalcode DESC)
limit 4,1;
4 here means leave first 4 and show the next 1.
Try this it works for me.
Very simple one query to find nth highest salary
SELECT DISTINCT(Sal) FROM emp ORDER BY Salary DESC LIMIT n,1