I am still learning SQL and can't find a proper way to find the following information:
I have created a table "employees" with the following columns:
'department', 'age', 'salary', 'bonus';
I am trying to design a query that will give me all employees that have someone the same age as them in another department and with a bonus superior to their salary.
(to be more precise, if someone in department 'SALES' has the same age as someone in department 'RESEARCH' and have a bonus that is superior to that guy in research's salary, then I would like to display both of them)
Is this possible to do in sql?
Thank you for your time,
-Tom
You can do this using exists. Because you care about the relationship in both direction, this is as simple as looking for people with the same age in the two departments but who do not have the same bonus:
select e.*
from employees e
where exists (select 1
from employees e2
where e2.department <> e.department and e2.age = e.age and
e2.bonus <> e.bonus
);
To get the pairs on the same row, use a self-join:
select e1.*, e2.*
from employees e1 join
employees e2
on e1.age = e2.age and e1.department <> e2.department and
e1.bonus > e2.bonus;
Related
http://studybyyourself.com/seminar/sql/exercises/8-3/?lang=en
Please provide data about all employees whose salary is higher or equal to the average salary of employees working in the same department (regardless if employees have left the company or not). Required attributes are last name, first name, salary and department name.
SELECT emp.Last_name, emp.First_name, emp.Salary, D.Name
FROM Employee AS emp
INNER JOIN Department AS D ON emp.Department_id = D.ID
WHERE emp.Salary >=
(
SELECT AVG(e.Salary)
FROM Employee AS e
GROUP BY e.Department_id
HAVING e.Department_id = emp.Department_id
)
Can anyone please help explain the solution? Specifically, what does the 'having' clause do in this case that allows the sub-query to work? I get stuck up until that point without the having clause and I expectedly get the 'subquery returns more than 1 row' error but I am not sure how the having clause is fixing the problem.
1
select *
from employees
where salary > (select max(salary) from employees where department_id=50)
2
select *
from employees e left join
employees d
on e.DEPARTMENT_ID =d.DEPARTMENT_ID
where d.salary > (select max(salary) from employees where department_id=50)
why the second query is giving multiple record
i want achieve the same result as of 1st query using join.....
Thanks in Advance......
Rocky, the first select is correct. Why do you want to do any join? Without further information the objective of the second select is not clear (nonsense).
I can't see the point about joining against the same table by DEPARTMENT_ID. Anyway, the problem about duplicates is because you are joining the same two tables by a key is not pk, basically you are multiplyng each employee for all the employees of the same department. This version eliminate duplicates but still has no improvement from the first one.
select *
from employees e left join
employees d
on e.employee_ID = d.employee_ID
where d.salary > (select max(salary) from employees where department_id=50)
You are probably looking for an anti join. This is a pattern mainly used in a young DBMS where IN and EXISTS clauses are slow compared to joins, because the developers focused on joins only.
You are looking for all employees whose salaries are greater than all salaries in department 50. With other words: WHERE NOT EXISTS a salary greater or equal in department 50.
Your query can hence be written as:
select *
from employees e
where not exists
(
select null
from employees e50
where e50.department_id = 50
and e50.salary >= e.salary
);
As an anti join (an outer join where you dismiss all matches):
select *
from employees e
left join employees e50 on e50.department_id = 50 and e50.salary >= e.salary
where e50.salary is null;
I don't yet understand this SQL statement:
select FIRST_NAME
from EMPLOYEES e
where DEP_ID != (select DEP_ID
from EMPLOYEES
where e.MANAGER_ID = EMPLOYEE_ID);
I would write your query as:
select e.FIRST_NAME
from EMPLOYEES e
where e.DEP_ID <> (select e2.DEP_ID
from EMPLOYEES e2
where e.MANAGER_ID = e2.EMPLOYEE_ID
);
This does not functionally change the query but it qualifies all column references and uses <> which is the traditional SQL operator for not equals.
What this query is doing is returning all employees whose department is not the same as their managers department.
How does it do this? The subquery is a correlated subquery. For each row in employees the subquery returns the department id of the manager.
The where clause then checks whether or not it matches the employee's manager.
This subquery will get the Manager's departments.
select DEP_ID from EMPLOYEES where e.MANAGER_ID = EMPLOYEE_ID
So the main query will just get the employees that not managers.
select FIRST_NAME from EMPLOYEES e where DEP_ID != (Managers dept_ID)
It's finding the employees who are not under a particular manager.
Let's see the inner part first:
select DEP_ID from EMPLOYEES where e.MANAGER_ID = EMPLOYEE_ID
This will fetch the department under particular manager
Now the outer part:
select FIRST_NAME from EMPLOYEES e where DEP_ID != <Departments under particular manager>
Now the result will the list of employees's first name not under that manager
This is the schema
\,
I try using inners but the results were trash
SELECT
employees.last_name AS last_name,
COUNT(employees.job_id) AS EMPLOYEES_Subordinates,
COUNT(employees.manager_id) AS Manager_Numbers
FROM
employees left
JOIN departments ON departments.manager_id = employees.manager_id
GROUP BY
employees.last_name
ORDER BY
EMPLOYEES_Subordinates desc;
( i really don't know how to show you the tables from hr)
If any 1 has the HR in Oracle Database and have time to help me , I gladly appreciate .
not quite sure but try something like this:
SELECT
e.LAST_NAME
,(SELECT COUNT(ee.EMPLOYEE_ID) FROM EMPLOYEES ee WHERE ee.MANAGER_ID = e.EMPLOYEE_ID) AS 'NUMBER OF WORKERS'
FROM EMPLOYEES e
WHERE MANAGER_ID IS NULL
The schema is as follows:
Employee: Fname, Lname, Ssn, Sex, Dno
Department: Dname, Dnumber, Mgr_ssn
Dnumber is the primary key of department, Ssn is the primary key of employee.
Dno is a foreign key referencing Dnumber.
I tried approaching the problem with this query:
SELECT Dnumber, count(ssn) from DEPARTMENT
INNER JOIN Employee
ON Dno = Dnumber
WHERE sex = ALL('M')
GROUP BY Dnumber
I thought the use of ALL would select only departments with all male employees, where the count would then be applied, however it is selecting all departments with male employees and then counting them.
I'm on the right tracks, and seems like I'm overlooking something trivial, but have tried looking up similar questions but have found no information.
Any pointers toward similar questions or advice on where i'm misstepping would be great.
This just screams "not exists":
select d.*
from department d
where not exists (select 1 from employee where d.dnumber = e.dno and d.sex = 'F');
Incidentally, assuming that all non-females are male would not work in many databases.
Your have multiple missteps in your query. First, ALL() applies to the list of values in the subquery. It doesn't have anything to do with the outer query. Second, it is filtering out all the females in the WHERE. That is fine if you want to count the numbers, but it give you nothing to determine if there are any females.
You could use HAVING (assuming that e.sex is defined as NOT NULL):
SELECT d.dnumber, d.dname
FROM department d
JOIN employee e
ON e.dno = d.dnumber
GROUP BY d.dnumber, d.name
HAVING COUNT(CASE WHEN e.sex = 'F' THEN 1 END) = 0;