Reputation: 5451
Find the top 2 employees who have the highest salary.
Table name is salary
, columns are name,salary
We can do this query by using limit command as
select * from salary order by salary DESC limit 0,2
But how to do this without using top and limit?
Upvotes: 4
Views: 16073
Reputation: 254
`I think this might work
select * from salary s1 where 2>=(select count(distinct id) from salary s2
where s1.salary<=s2.salary) order by salary desc;
This is co-related query.For every row in outer query,inner query will run and will return a count value of by comparing salary value of from outer query to every salary in table . It is like a nested loop of programming language
Say we have table Salary with two column id and salary
id Salary
1 1200
2 12345
3 123456
4 2535436
Output will be
id salary
4 2535436
2 123456
Upvotes: 0
Reputation: 113
SELECT e1.EmployeeID, e1.LastName, COUNT(DISTINCT e2.EmployeeID) AS sals_higher
FROM Employees e1
INNER JOIN Employees e2 ON e1.EmployeeID < e2.EmployeeID
GROUP BY e1.EmployeeID
HAVING sals_higher <= 2
ORDER BY e1.EmployeeID DESC
Visit https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_union3 and try the given piece of code, it gives you top 2 max EmployeeID.
Upvotes: 0
Reputation: 464
table structure
CREATE TABLE `emp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`salary` int(10) DEFAULT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
Mysql Query for nth term n represent nth number of item
SELECT salary
FROM emp
WHERE salary = (SELECT DISTINCT(salary)
FROM emp AS e1
WHERE (n) = (SELECT COUNT(DISTINCT(salary))
FROM emp AS e2
WHERE e1.salary <= e2.salary))
Upvotes: 0
Reputation: 37
+------+
| Sal |
+------+
| 3500 |
| 2500 |
| 2500 |
| 5500 |
| 7500 |
+------+
The following query will return the Nth Maximum element.
select SAL from EMPLOYEE E1 where
(N - 1) = (select count(distinct(SAL))
from EMPLOYEE E2
where E2.SAL > E1.SAL )
Upvotes: 0
Reputation: 53830
Here it is in MySQL:
SET @row := 0;
SELECT name, salary FROM
(SELECT name, salary, @row := @row + 1 AS Row FROM salary ORDER BY salary DESC)
AS derived1
WHERE Row < 3
There's still a caveat. If there are duplicate salaries, the results may be skewed. Ties won't be included in the results if the result set is greater than two rows, yet since the question is for the two employees with the highest salary and not the employees with the two highest salaries, this is the best I can do.
Maybe the correct answer is to ask, "What should I do in the case of duplicate salaries?"
Here's the trick if it absolutely has to be a single query:
SELECT name, salary FROM
(SELECT name, salary, @row := @row + 1 AS Row FROM (SELECT @row := 0) AS d1, salary)
AS d2
WHERE Row < 3
Upvotes: 1
Reputation: 64477
I believe this interview question is trying to direct you to nested selects, or common table expressions, or something of the sort. TOP 2
is the easy answer and obviously TOP
was implemented for just this purpose - the interview wants you to do it "manually".
In theory-code. Give each row a row count on the first (nested) select, then select from the results of that where the row count is less than one more than the number of rows you need, 3 in this case.
MySQL - Get row number on select
Nested select (pseudo-code):
select row_count, * from salary order by salary desc
Outer select:
select * from <nested select> where row_count < 3
I'm sorry this isn't MySQL code, but I only know SQL Server.
I have some SQL Server code that works using the row count:
declare @Salaries table
(
id int,
salary money
)
insert into @salaries (id, salary)
values (1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 4) -- A duplicating salary
;WITH Props AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY salary desc) AS RowNumber
FROM @Salaries
)
SELECT * FROM Props WHERE RowNumber < 3
This returns rows with ID 4 and 5.
Tackling Sachin Kainth's answer
I believe this answer is incorrect. Try the following SQL Server code:
declare @Salaries table
(
id int,
salary money
)
insert into @salaries (id, salary)
values (1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 4)
select * from @salaries where salary in -- "in" introduces the problem
(
SELECT MAX(E1.Salary)
FROM @salaries E1, @salaries E2
WHERE E1.Salary < E2.Salary
union
SELECT MAX(Salary)
FROM @salaries
)
This returns rows with ID 3, 4 and 5. Instead of just 4 and 5. This is because the outer select with clause where salary in
will take rows 3, 4 and 5, which all have their salary being returned by the nested select (which returns salary values 3 and 4).
Upvotes: 4
Reputation:
According to the SQL:2008 standard you can append FETCH FIRST 10 ROWS ONLY
to your query. Although, I've never tried this. So in your case you would have
SELECT * FROM salary ORDER BY salary DESC FETCH FIRST 2 ROWS ONLY
Upvotes: 1
Reputation: 46740
select * from salary where salary in
(
SELECT MAX(E1.Salary)
FROM Salary E1, Salary E2
WHERE E1.Salary < E2.Salary
union
SELECT MAX(Salary)
FROM Salary
)
Upvotes: 0