So, I have this schema:
Emp(eid: integer,ename: string,age: integer,salary: real)
Works(eid:integer,did: integer,pct_time: integer)
Dept(did:integer,budget: real,managerid:integer)
I want to return the employees whose salary is greater that any manager (regardless of their department).
select E.ename, D.did, E.eid
from Emp E
join Works W ON E.eid = W.eid
join Dept D ON D.did = W.did
where E.salary > (select E2.salary from Emp E2, Dept D2
where E2.eid = D2.managerid)
But the sub query statement is returning more than one row. How can I compare multiple rows from 2 tables to get the correct result? Grouping should work, right?
Your requirement could be translated to finding out an employee who exist a manager that have salary lower than his salary.
You could try this.
SELECT e.*
FROM emp e
WHERE EXISTS (SELECT 1
FROM emp e2 INNER JOIN
dept d2
ON e2.eid = d2.managerid
WHERE e2.salary < e.salary);
If you want to return the employees whose salary is greater that any manager, then why dont you just find out all the employees who have a salary greater than the minimun salary of all managers?
select E.ename, D.did, E.eid
from Emp E
join Works W ON E.eid = W.eid
join Dept D ON D.did = W.did
where E.salary > (select min(E2.salary)
from Emp E2, Dept D2
where E2.eid = D2.managerid)
I don't see why you need the works table. The question is about any manager. One way that you can write this is using > all:
select e.*
from emp e
where e.salary > all (select e2.salary
from emp e2 join
dept d2
on e2.eid = d2.managerid
);
You can run the subquery and see that it returns the salaries of all managers. You want employees whose salary is greater than those.
EDIT:
Does this version work?
select e.*
from emp e
where e.salary > (select MAX(e2.salary)
from emp e2 join
dept d2
on e2.eid = d2.managerid
);
The > all may not work as expected if any salaries are NULL.
Related
There are two tables
1) Employee
id | Name | Department | Dob
2) Salary
id | salary
I want to find the salary of the youngest and eldest employee in each department.
But using the the following query i am not able to get the correct id,salary.
SELECT salary.id,employee.Dept,salary.salary,MIN(employee.DoB)
from employee
INNER JOIN salary ON salary.id = employee.id GROUP by Dept
The above query is returning correct Dob but the ids and the salary are not matching with the Date of birth.
If you are running MySQL 8.0, just use window functions:
select *
from (
select
e.*,
s.salary,
row_number() over(partition by department order by dob asc) rn_asc,
row_number() over(partition by department order by dob desc) rn_desc
from employee e
inner join salary s on s.id = employee.id
) t
where 1 in (rn_asc, rn_desc)
In earlier versions, one option is to join with an aggregate query:
select e.*, s.salary
from employee e
inner join salary s on s.id = employee.id
inner join (
select department, min(dob) min_dob, max(dob) max_dob
from employee
group by department
) d on d.department = e.department and e.dob in (d.min_dob, d.max_dob)
I think I would use = twice with correlated subqueries:
select s.*, e.department
from salary join
employee e
on s.id = e.id
where e.dob = (select min(e2.dob) from employee e where e2.department = e.department) or
e.dob = (select max(e2.dob) from employee e where e2.department = e.department) ;
With an index on employee(department, dob), I would expect this to have very good performance.
I have two tables employees and departments.
Employees table has name, salary, department_id.
Departments table has department_id, department_name
I have to display the employee with the second highest(Literally the only one employee who has the second highest salary among every employee in the employees table) and his department_name using subqueries
select
max(e.salary),
d.department_name
from oehr_employees e
join oehr_departments d on(e.department_id = d.department_id)
where e.salary not in(
select max(salary) from oehr_employees
)
group by department_name
tried to do this one, but it shows only the second highest salary of each department. Have no idea what to do :/
Tried searching for answers but didn't quite get what I wanted.
If you want to do it using subqueries, you can try like following to get the details of employee(s) and department(s) with 2nd highest salary.
select e.name,e.salary,d.department_id,d.department_name
from
oehr_employees e
join oehr_departments d on e.department_id = d.department_id
WHERE e.salary IN (SELECT Max(salary)
FROM oehr_employees
WHERE salary NOT IN (SELECT Max(salary)
FROM oehr_employees));
If you just want the second more high salary, you can use limit and offset.
Would not it be a valid solution?
select e.salary,d.department_name
from oehr_employees e
join oehr_departments d on(e.department_id = d.department_id)
ORDER BY e.salary DESC LIMIT 1 OFFSET 1
Use ROW_NUMBER():
SELECT *
FROM (
SELECT
e.employee_id,
d.department_id,
e.salary,
ROW_NUMBER() OVER(ORDER BY e.salary DESC) rn
FROM oehr_employees e
INNER JOIN oehr_departments d
ON e.department_id = d.department_id
) x WHERE rn = 2
I would just modify your query a bit and add limit 1:
select e.*, d.department_name
from oehr_employees e join
oehr_departments d
on e.department_id = d.department_id)
where e.salary < (select max(e2.salary) from oehr_employees e2)
order by e.salary desc
limit 1;
This seems to meet the arcane requirement of using subqueries. And it is a reasonable approach.
I have this schema:
Emp(eid: integer,ename: string,age: integer,salary: real)
Works(eid:integer,did: integer,pct_time: integer)
Dept(did:integer,budget: real,managerid:integer)
and I'm trying to print the name and salary of each employee whose salary exceeds the budget of every department that he or she works in.
I have this SQL statement but it returns an empty column for ename and I'm not sure why. Can anyone help?
select E.ename, E.Salary
from Emp E
where E.salary > all (select D.budget
from Dept D, Works W
where E.eid = W.eid and D.did = W.did)
You can do that with a normal join
SELECT E.ename
FROM Emp E
JOIN Works W ON E.eid = W.eid
JOIN Dept D ON D.did = W.did
WHERE E.salary > D.budget
There is a table Employee as below:
I need finds out employees who earn more than their managers and I figure out two methods:
SELECT a.Name AS Employee FROM Employee a, Employee b WHERE a.Salary > b.Salary AND a.ManagerId = b.Id;
SELECT a.Name AS Employee FROM Employee a INNER JOIN Employee b ON a.Salary > b.Salary AND a.ManagerId = b.Id;
Both of them work well and have close speed.
What's the difference between them? Thanks.
Those queries are equivalent. But you should use the join syntax instead of commas in the from clause. INNER JOIN ON vs WHERE clause
Here's an alternative option which might have a better performance using exists:
select e.Name AS Employee
from employee e
where exists (
select 1
from employee e2
where e.managerid = e2.id and e.salary > e2.salary
)
I have the following query:
delete from departments
where department_id = (select department_id
from employees
where salary > 100000);
The query of course return more than 1 row, someone know how can I delete all the departments in just one query without do a function or something like that?
Use IN:
delete from departments
where department_id in (select department_id
from employees
where salary > 100000);
Alternatively join them
DELETE d
FROM departments d
INNER JOIN employees e ON d.department_id = e.department_id
WHERE e.salary > 100000;