Reputation: 382
I want to calculate highest nth salary in Oracle. I've already done with my solution but on google I found one query doing the same thing.
Here is the query
SELECT *
FROM Employee Emp1
WHERE (N - 1) = (SELECT COUNT(DISTINCT(Emp2.orig_salary))
FROM Employee Emp2
WHERE emp2.orig_salary > emp1.orig_salary)
Data
ID Name Birth Orig_Salary
2 John 15-JUL-97 2341
3 Joe 25-JAN-86 4321
4 Tom 13-SEP-06 2413
5 Jane 17-APR-05 7654
6 James 18-JUL-04 5679
7 Jodd 20-JUL-03 5438
8 Joke 01-JAN-02 8765
9 Jack 29-AUG-01 7896
I'm not not able to understand this query. After running inner query it will always gives me count of 8 after doing this it will go to where clause where it will pick salary which is higher than the outer query salary. How equal operator is working here in between inner and outer query and how comparison is happening.
Could any help me to understand how this query is working technically in back-end..?
Upvotes: 1
Views: 194
Reputation: 435
SELECT *
FROM Employee Emp1
WHERE (N - 1) = (SELECT COUNT(DISTINCT(Emp2.orig_salary))
FROM Employee Emp2 <--- cartesian product with same table
WHERE emp2.orig_salary > emp1.orig_salary) <---- but do the cartesian product only if line of salary of emp 2 is greater than the current line of Emp1 'salary
e.g assume there are only 3 lines in the table:
ID Name Birth Orig_Salary
2 John 15-JUL-97 2341
3 Joe 25-JAN-86 4321
4 Tom 13-SEP-06 5413
the main query will look at the first line --> 2 John 15-JUL-97 2341 <---, and subquery will return 2 because the salaries 4321 (emp2.orig_salary) and 5413 (emp2.orig_salary) are greater than 2341 (emp1.orig_salary)
the main query will then look at the second line --> 3 Joe 25-JAN-86 4321 <---, and subquery will return 1 because the salaries 5413 (emp2.orig_salary) is greater than 2341 (emp1.orig_salary)
when i say subquery, it is the
=(SELECT COUNT(DISTINCT(Emp2.orig_salary))
FROM Employee Emp2 <--- cartesian product with same table
WHERE emp2.orig_salary > emp1.orig_salary)
and the main query is
SELECT *
FROM Employee Emp1
WHERE
the returned value from the subquery is then compare to the where condition n-1, if the condition is satisfied, then it retrieves the line.
Upvotes: 2
Reputation: 1269953
There is no need to understand that query. The correct formulation is:
SELECT Emp1.*
FROM (SELECT Emp1.*, DENSE_RANK() OVER (ORDER BY Emp2.orig_salary) as seqnum
FROM Employee Emp1
) Emp1
WHERE seqnum = <n>;
This gives the details for the employees. If you just want the salary:
SELECT orig_salary
FROM (SELECT Emp1.*, DENSE_RANK() OVER (ORDER BY Emp2.orig_salary) as seqnum
FROM Employee Emp1
) Emp1
WHERE seqnum = <n> AND rownum = 1;
I should note that a simpler version of this is:
select distinct orig_salary
from employees
order by orig_salary desc
offset <n - 1>
fetch first 1 row only;
The use of a correlated subquery for this is a pleasant anachronism from the days when relational databases were not as powerful as they are now. It is of historical interest.
Upvotes: 1