SQL: Retrieve all records where has all joined - sql

Sorry, couldn't think of a better title.
I have 3 tables in Oracle XE. An EMPLOYEE table a PROJECT table and a WORK_ON table. An EMPLOYEE can WORK_ON many PROJECTs. I am trying to get the employee name who is working on all the projects.
EMPLOYEE Table
Emp_ID EMP_Name
1 Esther
2 Peter
3 Joan
4 Roger
5 Liam
PROJECT Table
Project_ID
1
2
3
WROKS_ON Table
Emp_ID Project_ID
1 3
2 1
2 2
2 3
3 1
3 2
4 1
4 2
4 3
Given the fields my result should be Peter and Roger.
Started with the following, but got stuck:
SELECT EMP_NameLOYEE.E_NAME
FROM EMP_NameLOYEE INNER JOIN
(PROJECT INNER JOIN WROKS_ON ON PROJECT.Project_ID = WROKS_ON.Project_ID) ON
EMP_NameLOYEE.Emp_ID = WROKS_ON.Emp_ID
WHERE WROKS_ON.Project_ID In (SELECT DISTINCT Project_ID FROM PROJECT);
Obviously this retrieves all the names of the employees that are working on each project duplicated, but not exactly what I want.

You can leave the project table out of it.
SELECT e.emp_id, COUNT(project_id)
FROM employee e
INNER JOIN works_on wo ON wo.emp_id = e.emp_id
GROUP BY e.emp_id
HAVING COUNT( project_id ) = (SELECT COUNT(*) FROM project);
SQL Fiddle

You need to generate all combinations of employees and projects with a cross join and left join the works table and check for row counts for each e_name.
SELECT e.E_NAME
FROM EMPLOYEE e
CROSS JOIN PROJECT p
LEFT JOIN WORKS_ON w ON p.Project_ID = w.Project_ID and e.emp_id=w.emp_id
GROUP by e.E_NAME
HAVING COUNT(*)=COUNT(w.project_id)

Related

How to write insert function or query

I have three tables which are very extensive, but I will give only a small version:
employee_position :
ID
position
1
Programmer
2
Administrator
3
Analyst
employee:
ID
name
1
Adam Smith
2
Sam Jones
3
Barbra Streisand
4
Dorothy Brown
employee_functions:
ID
employee_id
employee_position
1
1
3
2
3
1
Assuming what I need: if there is no employee in the employee_functions table [from the employee table] with an assigned position, then all positions in the employee_positions table should be assigned to him in this table.
I admit that I am not very fluent in SQL, so I would ask for help, can it be done with one query or can I do some function?
The final result for the given data (employee_functions):
ID
employee_id
employee_position
1
1
3
2
3
1
3
2
1
4
2
2
5
2
3
6
4
1
7
4
2
8
4
3
here is one way :
select employee_id ,employee_position from employee_functions f
union all
select e.id, p.id from employees e
cross join employee_position p
where e.id not in (select employee_id from employee_functions)
You can use insert . . . select, filtering out the employees who already have functions:
insert into employee_functions (employee_id, position_id)
select e.id, p.id
from employee e cross join
employee_positions ep
where not exists (select 1
from employee_functions ef
where ef.employee_id = e.id
);
insert into employee_functions (employee_id, position_id)
select e.id, p.id
from employee e cross join
employee_positions ep
where not exists (select 1
from employee_functions ef
where ef.employee_id = e.id
);

How to get a subset of a table using the count operator

SQL Server 2012.
Each enterprise has one or more teams. Each team can have sponsors or cannot have any sponsors.
Enterprise
Id Name
1 A
2 B
3 C
and the team table:
Team
Id Name EnterpiseId
1 For 1
2 Xor 2
3 Nor 2
4 Xur 1
5 Fir 3
6 Fte 2
and now the table sponsor
Sponsor
id Name TeamId
1 XX1 1
2 FC7 1
3 89U 3
Now I need to know how to present this table that shows only the enterprises that have at least one sponsor.
FINAL TABLE
Id Name
1 A
3 C
The enterprise B has 3 teams, but there are no sponsors for those 3 teams, so I want to show the enterprises that have sponsors which are "A" and "C".
Select A.id, A.name
FROM Enterprise A
LEFT JOIN Team B on A.Id=b.EnterpriseId
INNER JOIN Sponsor C on B.Id=C.TeamId
Where (SELECT COUNT(*) FROM Sponsor S INNER JOIN Team T on T.id=S.TeamId group by T.id)>0
This is not working. I am not used to use subsets which is likely the way to achieve the desired table. Thanks.
You can do this with JOINs. The GROUP BY is just to eliminate duplicates:
SELECT e.id, e.name
FROM Enterprise e JOIN
Team t
ON e.Id = t.EnterpriseId JOIN
Sponsor s
ON t.Id = s.TeamId
GROUP BY e.id, e.name;
The JOIN only matches teams that have sponsors.
If you were looking for more than one, then something like HAVING COUNT(*) > 1 would be called for.

how to display records which is present in employee but not present in department table

i want to get records which is present in employees table but not in department
i.e (Employees - department)
output should be like this
Employee(ID,Name), Department(Id,Name)
i tried this
select * from Employee as e
left join Department as d on e.DeptId = d.ID
sample data
ID Name DeptId Salary ID Name
1 krishna 1 5000 1 developer
2 rakesh 2 8000 2 trainer
3 sanjay 3 9000 3 programmer
4 swapna 4 6000 4 seo
6 shiva 6 4000 NULL NULL
i want to show records of shiva because he is in table employee but not in department table in sql server
Either use an OUTER JOIN as you've already done and filter by d.ID is null(as Dave has already shown). Or use NOT EXISTS which is my favorite:
select e.*
from Employee e
where not exists
(
select 1 from Department d
where e.DeptId = d.ID
)
Pros and cons of all approaches:
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
I had a little difficulty understanding the question but with your existing query a WHERE clause could be used to only show records that don't have an appartment.
select * from Employee as e
left join Department as d on e.DeptId = d.ID
WHERE d.ID is null
Alternatively
select
*
from Employee as e
WHERE e.ID not in (SELECT d.ID FROM Department d)

Sql query for 3 tables checks either of table

I am having 3 tables
1 : Employee
2 : Department
3 : Experts
I want the experts which belong to CmpId = 1
Employee :
id CmpId
1 2
2 1
3 1
Department
id CmpId
1 1
2 2
3 2
Experts :
id EmployeeId DepartmentId
1 1 2
2 2 null
3 null 1
4 2 1
5 null null
Let me guess that NULL in the expert table means that someone is an expert for all departments. If so:
select e.employeeid
from experts e join
departments d
on e.departmentid = d.id or e.departmentid is null;
If I understand the question correctly, the desired results based on the sample data should be Expert ID's 2,3 and 4.
Expert ID 2 has an Employee ID of 2, which has a CmpID of 1.
Expert ID 3 has a Department ID of 1, which has a CmpID of 1.
Expert ID 4 has an Employee ID of 2, which has a CmpID of 1 and a Department ID of 1 which has a CmpID of 1.
If this is in fact the desired result set, I would write the following query.
SELECT ex.id, ex.EmployeeID, ex.DepartmentID
FROM #Experts ex
LEFT JOIN #Department dep
ON ex.DepartmentID = dep.id
LEFT JOIN #Employee emp
ON ex.EmployeeID = emp.id
WHERE dep.CmpID = 1 OR emp.CmpID = 1
That will yield the following results.
id EmployeeID DepartmentID
2 2 NULL
3 NULL 1
4 2 1
INNER JOIN the three tables
If they need to be CmpId = 1 in BOTH (this returns nothing in your sample data but assuming it is a larger data set)
SELECT e.id, e.EmployeeId, e.DepartmentId
FROM Experts e
FULL OUTER JOIN Department d ON e.DepartmentId = d.id
FULL OUTER JOIN Employee em ON e.EmployeeId = em.id
WHERE d.CmpId = 1 AND em.CmpId = 1
If they need to be CmpId = 1 in Either
SELECT e.id, e.EmployeeId, e.DepartmentId
FROM Experts e
FULL OUTER JOIN Department d ON e.DepartmentId = d.id
FULL OUTER JOIN Employee em ON e.EmployeeId = em.id
WHERE d.CmpId = 1 OR em.CmpId = 1

Get the output based on column in the same table

I have a table which looks like this:
Employee table:
Employee_id E_Name Manager_Id
-------------------------------
1 p -
2 q 1
3 r 1
4 s 2
Here column Manager_Id denotes the manager's employee Id. Meaning for p there is no manager. for q and r employee with id 1 is manager (p). and for s employee with emp id 2 is manager.
I want to build a query which will return below result:
Employee_id E_Name Manager_Name
-------------------------------
1 p -
2 q p
3 r p
4 s q
table here has manager name instead of id.
How to achieve above? Thanks in advance
It can easily be done with a LEFT OUTER JOIN:
Try this:
SELECT a.EMPLOYEE_ID, a.E_NAME, b.E_NAME
FROM EMPLOYEE a left outer join EMPLOYEE b
on A.MANAGER_ID = B.EMPLOYEE_ID
you did not mentioned the database provider, but for MySQL, it is:
SELECT e.employee_id, e.e_name,COALESCE(m.e_name,'-') AS Manager_Name
FROM employee e
LEFT JOIN employee m ON m.employee_id = e.manager_id
Please try:
select
Employee_id,
E_Name,
(select E_Name from YourTable b where b.Employee_id=a.Manager_Id) as Manager_Name
from YourTable a