joins on four tables - sql

Consider a small example i have the below tables where it looks like this
Employee(eid(pkey),ename)
supply(sid(pkey),sname,eid(fkey))
supplier(suid(pkey),supname,sid(fkey))
item(iid(pkey),itemname,suid(fkey))
help in sql joins so the output be below format
i need to display all eids and ename even though they dont have item name related to them
eid , ename , itemname
to get item name

Using left joins, and starting from employee, even the employees without items will be selected.
select
e.eid,
e.ename,
i.itemname
from employee e
left join supply s on s.eid = e.eid
left join supplier su on su.sid = s.sid
left join item i on i.suid = su.suid
Without the requirement to also select employees without items, it's better to start joining from item:
select
i.itemname,
s.supname as suppliername,
su.sname as supplyname,
e.eid as empid,
e.ename as empname
from item i
left join supplier su on su.suid = i.suid
left join supply s on s.sid = su.sid
left join employee e on e.eid = s.eid

Related

find all employees' names who has a manager that lives in the same city as them

I am trying to figure out how to "find all employees' name who has a manager that lives in the same city as them." For this problem, we have two tables. We need to make a query.
"employee"
The employee table that we can refer to has both normal employees and managers
employeeid
name
projectid
city
1
jeff
1
new york
2
larry
1
new york
3
Linda
2
detroit
4
tom
2
LA
"Managertable"
Our manager table which we can refer to with mangerid = employeeid
projectid
mangerid
1
2
2
3
Right now I have found a way to get just the employees and filter out the managers, but now I am trying to figure out the next step to get to the comparison of managers and employees. Would this just be another subquery?
SELECT name
FROM employee e
WHERE employeeid not in(
SELECT mangerid
FROM Managertable pm
INNER JOIN employee e
ON pm.mangerid= e.employeeid);
Expected result :
employee name
jeff
I think the easient way to achieve this would be like this:
SELECT
e.*
FROM employee e
inner join Managertable mt on e.projectid = mt.projectid
inner join employee manager on mt.mangerid = manager.employeeid
WHERE
e.city = manager.city
and e.employeeid <> manager.employeeid;
One approach is a correlated subquery in which we look up the employee's manager's city.
select e.name
from employee e
where city =
(
select m.city
from managertable mt
join employee m on m.employeeid = mt.managerid
where mt.projectid = e.projectid
and m.employeeid <> e.employeeid
);
The same thing can be written with an EXISTS clause, if you like that better.
Based off the table structure you're showing, something like this might work
First find the employee ids of employees who have managers in the same city, then join it back on employee to retrieve all data from the table
;WITH same_city AS (
SELECT DISTINCT e.employeeid
FROM employee AS e
INNER JOIN managertable AS mt ON e.projectid = mt.projectid
INNER JOIN employee AS m ON mt.managerid = e.employeeid
WHERE e.city = m.city
)
SELECT e.*
FROM employee
INNER JOIN same_city AS sc ON e.employeeid = sc.employeeid
I don't see how projectid is relevant in your question because you didn't mention that as a requirement or restriction. Here's a method using a CTE to get the managers and their cities, then join to it to find employees who live in the same city as a manager.
with all_managers as (
select distinct m.managerid, e.city
from manager m
join employee e
on m.managerid = e.employeeid
)
select e.name
from employee e
join all_managers a
on e.city = a.city
and e.employeeid <> a.managerid;
name
jeff
But it you want us to assume that an employee reports to only that manager as listed in the projectid, then here's a modification to ensure that is met:
with all_managers as (
select distinct m.managerid, e.city, e.projectid
from manager m
join employee e
on m.managerid = e.employeeid
)
select e.name
from employee e
join all_managers a
on e.city = a.city
and e.projectid = a.projectid
and e.employeeid <> a.managerid;
View on DB Fiddle
You just need two joins:
one between "managers" and "employees" to gather managers information
one between "managers" and "employees" to gather employees information with respect to the manager's projectid and city.
SELECT employees.name
FROM managers
INNER JOIN employees managers_info
ON managers.mangerid = managers_info.employeeid
INNER JOIN employees
ON managers.projectid = employees.projectid
AND managers_info.employeeid <> employees.employeeid
AND managers_info.city = employees.city

SQL query to show Name and Department in a table

Can you please help me, I don't know how to create this query. I am a front end dev.
Expected result should be table with 2 columns
Name(one) DepartmentName(many)
The tables and their relationship are shown in this image:
You can do this with a couple of INNER JOINS. You don't need to reference the Location table in this query because Employee.LocationId is the same as EmployeeDepartment.LocationId.
This simple query will return all employee names and all department names they are related to. The employee name may be repeated, as this query puts only one department name in the column, so if an employee is in two departments, you get the employee name twice.
SELECT
EmployeeName = e.Name
,DepartmentName = d.Name
FROM Employee e
INNER JOIN EmployeeDepartment ed ON ed.LocationId = e.LocationId
INNER JOIN Department d ON d.id = ed.DepartmentId
This query is a bit more complicated, but returns each employee name only once, and the department names will be a comma-separated string of names. This is accomplished by using STUFF() in conjunction with FOR XML.
;WITH EmployeesAndDepartments AS
(
SELECT
EmployeeName = e.Name
,DepartmentName = d.Name
FROM Employee e
INNER JOIN EmployeeDepartment ed ON ed.LocationId = e.LocationId
INNER JOIN Department d ON d.id = ed.DepartmentId
)
SELECT
ead.EmployeeName
,Departments = STUFF((
SELECT ',' + DepartmentName
FROM EmployeesAndDepartments
FOR XML PATH('')
) , 1, 1, ''
)
FROM EmployeesAndDepartments ead
GROUP BY ead.EmployeeName
This should work
SELECT
e.Name
, d.Name AS DepartmentName
FROM
Employee e
LEFT OUTER JOIN
EmployeeDepartment ed
ON e.LocationId = ed.LocationId
LEFT OUTER JOIN
Department d
ON ed.DepartmentId = d.id
Note that the use of LEFT OUTER JOIN will return the employee even if they don't have a corresponding record in EmployeeDeparatment and/or Department. If you only want to retrieve employees that do have corresponding EmployeeDepartment and Department records, use INNER JOIN instead

Joining 3+ tables with join syntax in Oracle

I've been using joins for a long time, but it's always been the old syntax. Now I'm trying to figure out how to do basic inner joins with the JOIN syntax, and having trouble figuring it out.
Let's say I have 3 tables.
Employees:
EmployeeID EmployeeName DepartmentID
1 John Smith 2
2 Jane Doe 3
3 Mark Brown 1
Departments:
DepartmentID DepartmentName AreaID
1 Sales 2
2 Marketing 1
3 Opeations 3
Areas:
AreaID AreaName
1 Marketing
2 Sales
3 Opeartions
I need to get a list of all employee names with their departments and areas.
With the old syntax, I'd run the following query:
select e.EmployeeName, d.DepartmentName, a.AreaName
from employees e, departments d, areas a
where e.DepartmentID = d.DepartmentID
and d.AreaID = a.AreaID
With the new syntax it seems that I can only join employees with departments, but not departments with areas in the same query. Or should I perhaps use a subselect?
Try this.
select e.EmployeeName, d.DepartmentName, a.AreaName
from employees e join departments d on e.DepartmentID = d.DepartmentID
join areas a on d.AreaID = a.AreaID;
I find this explanation of joins to be pretty useful.
Your query will look like this:
SELECT e.EmployeeName, d.DepartmentName, a.AreaName
FROM employees e
INNER JOIN departments d on e.DepartmentID = d.DepartmentID
INNER JOIN areas a on d.AreaID = a.AreaID
You can try left joining the Employees, Departments, and Areas tables, in that order. We are meticulous here at Stack Overflow, and so we chose LEFT JOIN rather than INNER JOIN because it handles the possibility that an employee may not have been assigned to a department, in which case the query would display NA as the value.
SELECT e.EmployeeName,
COALESCE(d.DepartmentName, 'NA'),
COALESCE(a.AreaName, 'NA')
FROM Employees e
LEFT JOIN
Departments d
ON e.DepartmentID = d.DepartmentID
LEFT JOIN Areas a
ON d.AreaID = a.AreaID
The code that you've written is an alternative code for Inner Join.
You can use the code below.
So what I've done is Joined the Employee table to the Department table using the DepartmentID and Joined the Employee table to the Areas table using the AreaID.
Select e.EmployeeName
, d.DepartmentName
, a.AreaName
from employees e
INNER JOIN departments d
, areas a
ON e.DepartmentID = d.DepartmentID
INNER JOIN areas a
ON d.AreaID = a.AreaID

How to include rows with missing data in SQL Server 2008

Let's say I have a table a table of employees and another employee_address.
Additionally, I have a table of employee_email_address (employees don't have to have an email)
select
employee.emp_id,
employee_address.address,
employee_email_address.email
from
employees
inner join
employee_address on employee.emp_id = employee_address.emp_id
inner join
employee_email_address on employee_email_address.emp_id = employee.emp_id
but what this query is giving me is only the employees who have an address AND an email address....
How can I include rows for which there is no email_address for the employees? (Note, the email address is not null)
Thanks.
Use left join instead of inner join.
Try this query:
Select e.emp_id, ea.address, eea.email
from employees e left join
employee_address ea
on ea.emp_id = e.emp_id left join
employee_email_address eea
on eea.emp_id = e.emp_id;

Isa relationship query in sql

I have a disjoint relationship among my tables: Employee(empId PK, name), HourlyEmployee(empId PK FK, hourlySalary) empId is a reference to Employee.empId,
MonthlyEmployee(empId Pk FK, monthlySalary) empId is a reference to Employee.empId.
How can I create a query resulting AllEmployees(empId,name,hourlySalary,monthlySalary).
For all hourly employees monthlySalary will be null and for all monthly employess hourly salary will be null
Regards,
Tural
Use outer joins to get all employees no matter if they exist in HourlyEmployee or MonthlyEmployee (or neither of them).
select e.empid, e.name, h.hourlysalary, m.monthlysalary
from employee e
left outer join hourlyemployee h on h.empid = e.empid
left outer join monthlyemployee m on m.empid = e.empid;
select e.empid, e.name, h.hourlysalary, m.monthlysalary
from employee e
left outer join hourlyemployee h on h.empid = e.empid
left outer join monthlyemployee m on m.empid = e.empid
where (h.hourlysalary is null) or (m.monthlysalary is null);