MySQL query to print name and salary of each employee - mysql

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

Related

Finding the second highest salary by subqueries

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.

MySQL query to find employees salary greater than any manager

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.

How to get rid of Error Code 1242

I have the lines of code in My SQL Workbench, but I am receiving the error: Error Code: 1242. Subquery returns more than 1 row.
SELECT Fname, Lname, Dnum, Pno
FROM EMPLOYEE e, PROJECT p, WORKS_ON w
WHERE p.Dnum = (SELECT Dno FROM EMPLOYEE WHERE e.Ssn = w.Essn AND w.Pno = p.Pnumber)
I am trying to display a table of employees that are working on a project that is not sponsored by their department.
try this
SELECT Fname, Lname, Dnum, Pno
FROM EMPLOYEE e, PROJECT p, WORKS_ON w
WHERE p.Dnum in (SELECT Dno FROM EMPLOYEE WHERE e.Ssn = w.Essn AND w.Pno =
p.Pnumber);
use in clause instad =
Optimized query:
SELECT Fname, Lname, Dnum, Pno
FROM EMPLOYEE e
INNER JOIN WORKS_ON w ON e.Ssn = w.Essn
INNER JOIN PROJECT p ON w.Pno = p.Pnumber AND p.Dnum = e.Dno

Is Inner Join needed when operating on one table?

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
)

SQL aggregation group by

I have an employee table and a leave_allocation table which has a one-to-many relationship, Each employee has a number of leave allocations over a period of time. I would like to get the LATEST allocation for each employee.
I tried the query but the date and the days values do not correlate to the same row
select e.employee_number, e.nme, MAX(l.date), l.days
from employee e, leave_allocation l
where l.employee_id = e.employee_id
group by e.employee_number, e.nme
How can I get the latest allocation per employee?
SELECT e.employee_number
,e.nme
,l.days
FROM employee e
, leave_allocation l
,(SELECT employee_id
,MAX(DATE) date
FROM leave_allocation
GROUP BY employee_id) m
WHERE l.employee_id = e.employee_id
AND l.employee_id = m.employee_id
AND l.date = m.date
If there can be multiple rows with same employee_number and date, then you need to sum.
SELECT e.employee_number
,e.nme
,sum(l.days)
FROM employee e
, leave_allocation l
,(SELECT employee_id
,MAX(DATE) date
FROM leave_allocation
GROUP BY employee_id) m
WHERE l.employee_id = e.employee_id
AND l.employee_id = m.employee_id
AND l.date = m.date
GROUP BY e.employee_number
,e.nme
Place the MAX() date in a subquery:
SELECT e.employee_number, e.nme, l.leavedate, la.days
FROM employee e
INNER JOIN
(
SELECT Max(date) leavedate, employee_id
FROM leave_allocation
GROUP BY employee_id
) l
ON e.employee_id = l.employee_id
INNER JOIN leave_allocation la
ON l.employee_id = la.employee_id
AND l.leavedate = la.date
I also switched the query to use ANSI join syntax instead of commas between the tables.
Try this one,
SELECT e.employee_number, e.nme, c.maxDate, l.days
FROM employee e
INNER JOIN leave_allocation l
ON l.employee_id = e.employee_id
INNER JOIN
(
select employee_id, MAX(date) maxDate
from leave_allocation
group by employee_id
) c ON c.employee_id = l.employee_ID AND
c.maxDate = l.date