Related
Is there any direct way of using row_number() function? I want to find 2 nd highest salary
SELECT DISTINCT id
,salary
,depid
,ROW_NUMBER() OVER (
PARTITION BY depid ORDER BY salary DESC
) AS rownum
FROM emp
WHERE rownum = 2;
It gives an error, However the below code works fine.
SELECT *
FROM (
SELECT DISTINCT id
,salary
,depid
,ROW_NUMBER() OVER (
PARTITION BY depid ORDER BY salary DESC
) AS rownum
FROM emp
) AS t
WHERE t.rownum = 2;
Is any way of directly using the row_number() function as in the first option which is giving the error?
You can not use the alias name of the same query as the condition for the where clause. You also can not use windowed queries as a passing condition in the where clause.
Here is a detailed explanation Why no windowed functions in where clauses?. It is so you need another query outside the inner query and needs to write sub-query.
You can get the Nth highest salary in SQL Server from the below query.
SELECT TOP 1 salary
FROM (
SELECT DISTINCT TOP N salary
FROM <YourTableNameHere>
ORDER BY salary DESC
) AS TEMP
ORDER BY salary
This query will give you the second highest salary ? No
SELECT id
,salary
,depid
from emp
ORDER BY salary DESC
OFFSET 1 ROWS
FETCH FIRST 1 ROWS ONLY;
Well actually, it will give you the salary that is on the second position when you order the salary's from highest to lowest... So if the highest is 100 and the second highest is 100 then you will get 100 as a result. To conclude this will return a row on the second place depending on the order by clause...
This next query will give you the second highest salary :
SELECT max(id)
, salary
, max(depid)
from emp
group by salary
ORDER BY salary DESC
OFFSET 1 ROWS
FETCH FIRST 1 ROWS ONLY;
But be aware, in case you have two employees from two different departments with the same salary then it will return you the one with the higher id and it will return the higher department id which can be incorrect.
And finally this will give you one employee that has a second largest salary with correct data:
SELECT id
, salary
, depid
from emp
where id = (SELECT max(id)
from emp
group by depid, salary
ORDER BY salary DESC
OFFSET 1 ROWS
FETCH FIRST 1 ROWS ONLY);
First, you want dense_rank(), not row_number() if you want the second highest value -- ties might get in the way otherwise.
You can use an arithmetic trick:
SELECT TOP (1) WITH TIES id, salary, depid
FROM emp
ORDER BY ABS(DENSE_RANK() over (PARTITION BY depid ORDER BY salary DESC) - 2)
The "-2" is an arithmetic trick to put the "second" values highest.
That said, I would stick with the subquery because the intent in clearer.
You could use a variation on the trick that uses a TOP 1 WITH TIES in combination with an ORDER BY ROW_NUMBER
SELECT TOP 1 WITH TIES
id,
salary,
depid
FROM emp
ORDER BY IIF(2 = ROW_NUMBER() OVER (PARTITION BY depid ORDER BY salary DESC), 1, 2)
But this trick does have the disadvantage that you can't sort it by something else.
Well, not unless you wrap it in a sub-query and sort the outer query.
A test on rextester here
I prefer to use dense_rank() instead of row_number() function with CTE (common table expression) for the scenario you have mentioned. CTE is modern, easy to use and have many cool features like it is memory resident, it can be used for DUI operations, it make code easy to understand etc.
To find Nth highest salary, the CTE look like
;with findnthsalary
as
(
select empid, deptid, salary,
dense_rank() over(partition by deptid order by salary desc) salrank
from
Employee
)
select distinct id, deptid, salary
from findnthsalary
where salrank = N
I used dense_rank() because if you use row_number() it will produce the wrong result in case multiple employees have the same salary in the same department.
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 find third or nth maximum salary from salary table(EmpID, EmpName, EmpSalary) in optimized way?
Row Number :
SELECT Salary,EmpName
FROM
(
SELECT Salary,EmpName,ROW_NUMBER() OVER(ORDER BY Salary) As RowNum
FROM EMPLOYEE
) As A
WHERE A.RowNum IN (2,3)
Sub Query :
SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary
)
Top Keyword :
SELECT TOP 1 salary
FROM (
SELECT DISTINCT TOP n salary
FROM employee
ORDER BY salary DESC
) a
ORDER BY salary
Use ROW_NUMBER(if you want a single) or DENSE_RANK(for all related rows):
WITH CTE AS
(
SELECT EmpID, EmpName, EmpSalary,
RN = ROW_NUMBER() OVER (ORDER BY EmpSalary DESC)
FROM dbo.Salary
)
SELECT EmpID, EmpName, EmpSalary
FROM CTE
WHERE RN = #NthRow
Try this
SELECT TOP 1 salary FROM (
SELECT TOP 3 salary
FROM employees
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
For 3 you can replace any value...
If you want optimize way means use TOP Keyword, So the nth max and min salaries query as follows but the queries look like a tricky as in reverse order by using aggregate function names:
N maximum salary:
SELECT MIN(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP N EmpSalary FROM Salary ORDER BY EmpSalary DESC)
for Ex: 3 maximum salary:
SELECT MIN(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP 3 EmpSalary FROM Salary ORDER BY EmpSalary DESC)
N minimum salary:
SELECT MAX(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP N EmpSalary FROM Salary ORDER BY EmpSalary ASC)
for Ex: 3 minimum salary:
SELECT MAX(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP 3 EmpSalary FROM Salary ORDER BY EmpSalary ASC)
Too simple if you use the sub query!
SELECT MIN(EmpSalary) from (
SELECT EmpSalary from Employee ORDER BY EmpSalary DESC LIMIT 3
);
You can here just change the nth value after the LIMIT constraint.
Here in this the Sub query Select EmpSalary from Employee Order by EmpSalary DESC Limit 3; would return the top 3 salaries of the Employees. Out of the result we will choose the Minimum salary using MIN command to get the 3rd TOP salary of the employee.
Replace N with your Max Number
SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
Explanation
The query above can be quite confusing if you have not seen anything like it before – the inner query is what’s called a correlated sub-query because the inner query (the subquery) uses a value from the outer query (in this case the Emp1 table) in it’s WHERE clause.
And Source
Third or nth maximum salary from salary table without using subquery
select salary from salary
ORDER BY salary DESC
OFFSET N-1 ROWS
FETCH NEXT 1 ROWS ONLY
For 3rd highest salary put 2 in place of N-1
SELECT Salary,EmpName
FROM
(
SELECT Salary,EmpName,DENSE_RANK() OVER(ORDER BY Salary DESC) Rno from EMPLOYEE
) tbl
WHERE Rno=3
SELECT EmpSalary
FROM salary_table
GROUP BY EmpSalary
ORDER BY EmpSalary DESC LIMIT n-1, 1;
Refer following query for getting nth highest salary. By this way you get nth highest salary in MYSQL. If you want get nth lowest salary only you need to replace DESC by ASC in the query.
Method 1:
SELECT TOP 1 salary FROM (
SELECT TOP 3 salary
FROM employees
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
Method 2:
Select EmpName,salary from
(
select EmpName,salary ,Row_Number() over(order by salary desc) as rowid
from EmpTbl)
as a where rowid=3
In 2008 we can use ROW_NUMBER() OVER (ORDER BY EmpSalary DESC) to get a rank without ties that we can use.
For example we can get the 8th highest this way, or change #N to something else or use it as a parameter in a function if you like.
DECLARE #N INT = 8;
WITH rankedSalaries AS
(
SELECT
EmpID
,EmpName
,EmpSalary,
,RN = ROW_NUMBER() OVER (ORDER BY EmpSalary DESC)
FROM salary
)
SELECT
EmpID
,EmpName
,EmpSalary
FROM rankedSalaries
WHERE RN = #N;
In SQL Server 2012 as you might know this is performed more intuitively using LAG().
Answering this question from the point of view of SQL Server as this is posted in the SQL Server section.
There many approaches of getting Nth salary and we can classify these approaches in two sections one using ANSI SQL approach and other using TSQL approach. You can also check out this find nth highest salary youtube video which shows things practically. Let’s try to cover three ways of writing this SQL.
Approach number 1: - ANSI SQL: - Using Simple order by and top keyword.
Approach number 2: - ANSI SQL: - Using Co-related subqueries.
Approach number 3: - TSQL: - using Fetch Next
Approach number 1: - Using simple order by and top.
In this approach we will using combination of order by and top keyword. We can divide our thinking process in to 4 steps: -
Step 1: - Descending :- Whatever data we have first make it descending by using order by clause.
Step 2:- Then use TOP keyword and select TOP N. Where N stands for which highest salary rank you want.
Step 3: - Ascending: - Make the data ascending.
Step 4:- Select top 1 .There you are done.
So, if you put down the above 4 logical steps in SQL it comes up something as shown below.
Below is the text of SQL in case you want to execute and test the same.
select top 1 * from (select top 2 EmployeeSalary from tblEmployee
order by EmployeeSalary desc) as innerquery order by EmployeeSalary
asc
Parameterization issue of Approach number 1
One of the biggest issues of Approach number 1 is “PARAMETERIZATION”.
If you want to wrap up the above SQL in to a stored procedure and give input which top salary you want as a parameter, it would be difficult by Approach number 1.
One of the things you can do with Approach number 1 is make it a dynamic SQL but that would not be an elegant solution. Let’s check out Approach number 2 which is an ANSI SQL approach.
Approach number 2: - Using Co-related subqueries.
Below is how co-related subquery solution will look like. In case you are new to Co-related subquery. Co-related subquery is a query which a query inside query. The outer query first evaluates, sends the record to the inner query, inner query then evaluates and sends it to the outer query.
“3” in the query is the top salary we want to find out.
Select E1.EmployeeSalary from tblEmployee as E1 where 3=(Select
count(*) from tblEmployee as E2 Where
E2.EmployeeSalary>=E1.EmployeeSalary)
So in the above query we have an outer query:-
Select E1.EmployeeSalary from tblEmployee as E1
and inner query is in the where clause. Watch those BOLD’s which indicate how the outer table alias is referred in the where clause which makes co-related evaluate inner and outer query to and fro: -
where 3=(Select count(*) from tblEmployee as E2 Where
E2.EmployeeSalary>=E1.EmployeeSalary)
So now let’s say you have records like 3000, 4000 ,1000 and 100 so below will be the steps: -
First 3000 will be send to the inner query.
Inner query will now check how many record values are greater than or equal to 3000. If the number of record counts is not equal, it will take next value which is 4000. Now for 3000 there are only 2 values which is greater than or equal, 3000 and 4000. So, Is number record count 2>-=3? .NO, so it takes second value which is 4000.
Again for 4000 how many record values are greater than or equal. If the number of record count is not equal, it will take next value which is 1000.
Now 1000 has 3 records more or equal than 1000, (3000,4000 and 1000 himself). This is where co-related stops and exits and gives the final output.
Approach number 3: - TSQL fetch and Next.
Third approach is by using TSQL. By using Fetch and Next, we can get the Nth highest easily.
But please do note, TSQL code will not work for other databases we will need to rewrite the whole code again.
It would be a three-step process:-
Step 1 Distinct and Order by descending: - First apply distinct and order by which made the salaries descending as well as weed off the duplicates.
Step 2 Use Offset: - Use TSQL Offset and get the top N-1 rows. Where N is the highest salary we want to get. Offset takes the number of rows specified, leaving the other rows. Why (N-1) because it starts from zero.
Step 3 Use Fetch: - Use fetch and get the first row. That row has the highest salary.
The SQL looks something as shown below.
Performance comparison
Below is the SQL plan for performance comparison.
Below is the plan for top and order by.
Below is the plan for co-related queries. You can see the number of operators are quiet high in numbers. So surely co-related would perform bad for huge data.
Below is TSQL query plan which is better than cor-related.
So, summing up we can compare more holistically as given in the below table.
declare #maxNthSal as nvarchar(20)
SELECT TOP 3 #maxNthSal=GRN_NAME FROM GRN_HDR ORDER BY GRN_NAME DESC
print #maxNthSal
To get third highest value from table
SELECT * FROM tableName ORDER BY columnName DESC LIMIT 2, 1
This is one of the popular question in any SQL interview. I am going to write down different queries to find out the nth highest value of a column.
I have created a table named “Emloyee” by running the below script.
CREATE TABLE Employee([Eid] [float] NULL,[Ename] [nvarchar](255) NULL,[Basic_Sal] [float] NULL)
Now I am going to insert 8 rows into this table by running below insert statement.
insert into Employee values(1,'Neeraj',45000)
insert into Employee values(2,'Ankit',5000)
insert into Employee values(3,'Akshay',6000)
insert into Employee values(4,'Ramesh',7600)
insert into Employee values(5,'Vikas',4000)
insert into Employee values(7,'Neha',8500)
insert into Employee values(8,'Shivika',4500)
insert into Employee values(9,'Tarun',9500)
Now we will find out 3rd highest Basic_sal from the above table using different queries.
I have run the below query in management studio and below is the result.
select * from Employee order by Basic_Sal desc
We can see in the above image that 3rd highest Basic Salary would be 8500. I am writing 3 different ways of doing the same. By running all three mentioned below queries we will get same result i.e. 8500.
First Way: - Using row number function
select Ename,Basic_sal
from(
select Ename,Basic_Sal,ROW_NUMBER() over (order by Basic_Sal desc) as rowid from Employee
)A
where rowid=2
Select TOP 1 Salary as '3rd Highest Salary' from (SELECT DISTINCT TOP 3 Salary from Employee ORDER BY Salary DESC) a ORDER BY Salary ASC;
I am showing 3rd highest salary
SELECT MIN(COLUMN_NAME)
FROM (
SELECT DISTINCT TOP 3 COLUMN_NAME
FROM TABLE_NAME
ORDER BY
COLUMN_NAME DESC
) AS 'COLUMN_NAME'
--nth highest salary
select *
from (select lstName, salary, row_number() over( order by salary desc) as rn
from employee) tmp
where rn = 2
--(nth -1) highest salary
select *
from employee e1
where 1 = (select count(distinct salary)
from employee e2
where e2.Salary > e1.Salary )
Optimized way: Instead of subquery just use limit.
select distinct salary from employee order by salary desc limit nth, 1;
See limit syntax here http://www.mysqltutorial.org/mysql-limit.aspx
By subquery:
SELECT salary from
(SELECT rownum ID, EmpSalary salary from
(SELECT DISTINCT EmpSalary from salary_table order by EmpSalary DESC)
where ID = nth)
Try this Query
SELECT DISTINCT salary
FROM emp E WHERE
&no =(SELECT COUNT(DISTINCT salary)
FROM emp WHERE E.salary <= salary)
Put n= which value you want
set #n = $n
SELECT a.* FROM ( select a.* , #rn = #rn+1 from EMPLOYEE order by a.EmpSalary desc ) As a where rn = #n
MySQL tested solution, assume N = 4:
select min(CustomerID) from (SELECT distinct CustomerID FROM Customers order by CustomerID desc LIMIT 4) as A;
Another example:
select min(country) from (SELECT distinct country FROM Customers order by country desc limit 3);
Try this code :-
SELECT *
FROM one one1
WHERE ( n ) = ( SELECT COUNT( one2.salary )
FROM one one2
WHERE one2.salary >= one1.salary
)
Find Nth highest salary from a table. Here is a way to do this task using dense_rank() function.
select linkorder from u_links
select max(linkorder) from u_links
select max(linkorder) from u_links where linkorder < (select max(linkorder) from u_links)
select top 1 linkorder
from ( select distinct top 2 linkorder from u_links order by linkorder desc) tmp
order by linkorder asc
DENSE_RANK :
1. DENSE_RANK computes the rank of a row in an ordered group of rows and returns the rank as a NUMBER. The ranks are consecutive integers beginning with 1.
2. This function accepts arguments as any numeric data type and returns NUMBER.
3. As an analytic function, DENSE_RANK computes the rank of each row returned from a query with respect to the other rows, based on the values of the value_exprs in the order_by_clause.
4. In the above query the rank is returned based on sal of the employee table. In case of tie, it assigns equal rank to all the rows.
WITH result AS (
SELECT linkorder ,DENSE_RANK() OVER ( ORDER BY linkorder DESC ) AS DanseRank
FROM u_links )
SELECT TOP 1 linkorder FROM result WHERE DanseRank = 5
In SQL Server 2012+, OFFSET...FETCH would be an efficient way to achieve this:
DECLARE #N AS INT;
SET #N = 3;
SELECT
EmpSalary
FROM
dbo.Salary
ORDER BY
EmpSalary DESC
OFFSET (#N-1) ROWS
FETCH NEXT 1 ROWS ONLY
select * from employee order by salary desc;
+------+------+------+-----------+
| id | name | age | salary |
+------+------+------+-----------+
| 5 | AJ | 20 | 100000.00 |
| 4 | Ajay | 25 | 80000.00 |
| 2 | ASM | 28 | 50000.00 |
| 3 | AM | 22 | 50000.00 |
| 1 | AJ | 24 | 30000.00 |
| 6 | Riu | 20 | 20000.00 |
+------+------+------+-----------+
select distinct salary from employee e1 where (n) = (select count( distinct(salary) ) from employee e2 where e1.salary<=e2.salary);
Replace n with the nth highest salary as number.
SELECT TOP 1 salary FROM ( SELECT TOP n salary FROM employees ORDER BY salary DESC Group By salary ) AS emp ORDER BY salary ASC
(where n for nth maximum salary)
Just change the inner query value: E.g Select Top (2)* from Student_Info order by ClassID desc
Use for both problem:
Select Top (1)* from
(
Select Top (1)* from Student_Info order by ClassID desc
) as wsdwe
order by ClassID
This question already has answers here:
How to get second largest or third largest entry from a table [duplicate]
(12 answers)
SELECTing top N rows without ROWNUM?
(5 answers)
Closed 9 years ago.
I have a employee table in oracle with name,salary and other details.
I am trying to get the second highest salary but not able to fetch.
This one working fine
with e_salary as (select distinct salary from employee)
select salary from e_salary
order by salary desc
And gives output:
450000
61000
60000
50000
40000
30000
20000
6000
but when i am using the same query to fetch second highest row not getting any output
select salary
from ( with e_salary as (select distinct salary from employee)
select salary from e_salary order by salary desc)
where rownum = 2
but as i replace the rownum=2 with rownum<2 it gives output of first two records. Please someone explain why rownum=2 is not working
This will work:
select salary from ( select salary , rownum as rn from (select salary
from e_salary order by salary desc)) where rn = 2;
Why it doesn't work:
When assigning ROWNUM to a row, Oracle starts at 1 and only only increments the value when a row is selected; that is, when all conditions in the WHERE clause are met. Since our condition requires that ROWNUM is greater than 2, no rows are selected and ROWNUM is never incremented beyond 1.
Hope u are clear right now.
select ename ,sal ,rank() over (order by sal desc) ranking from emp;
Try this one.
Follow this link, all the things regarding nth highest row is given over here in oracle:
http://www.oratable.com/nth-highest-salary-in-oracle/
Use of rownum is a tricky affair. Safest bet is to use it only when you want to limit the number of results to be shown. For example rownum<2 or rownum<=5.
Why rownum=2 will not work?
Read here - http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html
In summary, this is how oracle execute a query
The FROM/WHERE clause goes first.
ROWNUM is assigned and incremented to each output row from the FROM/WHERE clause.
SELECT is applied.
GROUP BY is applied.
HAVING is applied.
ORDER BY is applied.
rownum<=2 clause will get converted to
ROWNUM = 1
for x in
( select * from emp )
loop
exit when NOT(ROWNUM <= 2)
OUTPUT record to temp
ROWNUM = ROWNUM+1
end loop
SORT TEMP
if you change exit when NOT(ROWNUM <= 2) with rownnum=2, you can see it will fail in the first run itself
So if I cannot use rownum, what can I use. Try using row_number() http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm
It works something like
SELECT last_name FROM
(SELECT last_name, ROW_NUMBER() OVER (ORDER BY last_name) R FROM employees)
WHERE R BETWEEN 51 and 100;
rownum in a condition stops evaluating the first time it fails. On the first row returned, rownum is 1, therefore it fails the rownum = 2 test and stops trying. There's an excellent post about it here.
To get the second-highest salary, use the Oracle analytical DENSE_RANK function:
SELECT DISTINCT Salary FROM (
SELECT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) AS SalaryRank
FROM e_salary)
WHERE SalaryRank = 2
Note that if there's a tie for second, the query could return more than one value. That's why the outer SELECT is a SELECT DISTINCT.
First you should understand what the rownum is. Let me give you an example,
you want to get data with a filter and rownum=2,
first Oracle executes the sql with filter and get the first record,
give it the rownum 1,
and then compare it the rownum filter rownum=2, which doesn't match, so discard record,
then get second record, give it rownum=1(if the first record is matched then the rownum will be 2) too, then do the compare............
So you can find the reason.
Without using rownum command you can get the second highest salary by using this query:
select MAX(Salary) from Employee
WHERE Salary NOT IN
(select MAX(Salary) from Employee )
or,
select MAX(Salary) from Employee
WHERE Salary <>
(select MAX(Salary) from Employee )
query for nth highest:
SELECT * FROM Employee Emp1
WHERE (N-1) =
(SELECT COUNT(DISTINCT(Emp2.Salary))FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
From what I understand, rownum numbers the rows in a result set.
So, in your example:
select * from table1 where rownum=2
How many rows are there going to be in the result set? Therefore, what rownum would be assigned to such a row? Can you see now why no result is actually returned?
In general, you should avoid relying on rownum, or any features that imply an order to results. Try to think about working with the entire set of results.
With that being said, I believe the following would work:
select * from (select rownum as rn,table1.* from table1) as t where t.rn = 2
Because in that case, you're numbering the rows within the subquery.
I want to write a query to display employees getting top 3 salaries
SELECT *
FROM (SELECT salary, first_name
FROM employees
ORDER BY salary desc)
WHERE rownum <= 3;
But I dont understand how this rownum is calculated for the nested query
will this work or if it has problem ,request you to please make me understand:
SELECT *
FROM (SELECT salary, first_name
FROM employees
ORDER BY salary )
WHERE rownum >= 3;
I went through this link Oracle/SQL: Why does query "SELECT * FROM records WHERE rownum >= 5 AND rownum <= 10" - return zero rows ,but it again points to a link, which does not gives the answer
a_horse_with_no_name's answer is a good one,
but just to make you understand why you're 1st query works and your 2nd doesn't:
When you use the subquery, Oracle doesn't magically use the rownum of the subquery, it just gets the data ordered so it gives the rownum accordingly, the first row that matches criteria still gets rownum 1 and so on. This is why your 2nd query still returns no rows.
If you want to limit the starting row, you need to keep the subquery's rownum, ie:
SELECT *
FROM (SELECT * , rownum rn
FROM (SELECT salary, first_name
FROM employees
ORDER BY salary ) )sq
WHERE sq.rn >= 3;
But as a_horse_with_no_name said there are better options ...
EDIT: To make things clearer, look at this query:
with t as (
select 'a' aa, 4 sal from dual
union all
select 'b' aa, 1 sal from dual
union all
select 'c' aa, 5 sal from dual
union all
select 'd' aa, 3 sal from dual
union all
select 'e' aa, 2 sal from dual
order by aa
)
select sub.*, rownum main_rn
from (select t.*, rownum sub_rn from t order by sal) sub
where rownum < 4
note the difference between the sub rownum and the main rownum, see which one is used for criteria
The "rownum" of a query is assigned before an order by is applied to the result. So the rownumw 42 could wind up being the first row.
Generally speaking you need to use the rownum from the inner query to limit your overall output. This is very well explained in the manual:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/pseudocolumns009.htm#i1006297
I prefer using row_number() instead, because you have much better control over the sorting and additionally it's a standard feature that works on most modern DBMS:
SELECT *
FROM (
SELECT salary,
first_name,
row_number() over (order by salary) as rn
FROM employees
)
WHERE rn <= 3
ORDER BY salary;
You should understand that the derived table in this case is only necessary to be able to apply a condition on the generated rn column. It's not there to avoid the "rownum problem" as the value of row_number() only depends on the order specifiy in the over(...) part (it is independent of any ordering applied to the query itself)
Note this would not return employees that have the same salary and would still fall under the top three. In that case using dense_rank() is probably more approriate.
if you want to select the people with the top 3 salaries.. perhaps you should consider using analytics.. something more like
SELECT *
FROM (
SELECT salary, first_name, dense_rank() over(order by salary desc) sal_rank
FROM employees
)
WHERE sal_rank <= 3
ie ALL people with the 3rd highest(ranked) salary amount(or more)
the advantage of this over using plain rownum is if you have multiple people with the same salary they will all be returned.
Easiest way to print 5th highest salary.
SELECT MIN(SALARY) FROM (SELECT SALARY FROM EMPLOYEES ORDER BY DESC) WHERE ROWNUM BETWEEN 1 AND 5
according to same if u want to print 3rd or 4th highest salary then just chage last value.(means instead of 5 use 3 or 4 you will get 3rd or 4th highest salary).
SELECT MIN(SALARY) FROM (SELECT SALARY FROM EMPLOYEES ORDER BY DESC) WHERE ROWNUM BETWEEN 1 AND 4
SELECT MIN(SALARY) FROM (SELECT SALARY FROM EMPLOYEES ORDER BY DESC) WHERE ROWNUM BETWEEN 1 AND 3
SELECT EMPNO,
SAL,
(SELECT SUM(E.SAL) FROM TEST E WHERE E.EMPNO <= T.EMPNO) R_SAL
FROM (SELECT EMPNO, SAL FROM TEST ORDER BY EMPNO) T
Easiest way to find the top 3 employees in oracle returning all fields details:
SELECT *
FROM (
SELECT * FROM emp
ORDER BY sal DESC)
WHERE rownum <= 3 ;
select *
from (
select emp.*,
row_number() over(order by sal desc)r
from emp
)
where r <= 3;
SELECT Max(Salary)
FROM Employee
WHERE Salary < (SELECT Max(salary) FROM employee WHERE Salary NOT IN (SELECT max(salary) FROM employee))
ORDER BY salary DESC;