Joining 3+ tables with join syntax in Oracle - sql

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

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

I need to get number of employees per depatment

This gets me the number of employees per department
SELECT department, COUNT(idEmployees) empCount
FROM employees
GROUP BY department;
You could join on departments to get the buildingID, and then group by that:
SELECT buildingID, COUNT(*)
FROM employees e
JOIN department d ON e.department = d.departmentID
GROUP BY buildingID
i think this is the solution
select d.buildingID, count(e.ID)
from department d
inner join employees e
on d.departmentID = e.department
group by d.buildingID
This question can be answered in two ways. Firstly, if all employees of a department must be attached in a building. Secondly few employees of a department are attached to a building.
For one where employees are attached to a building it's mandatory
SELECT d.buildingId
, COUNT(e.id) count_employee
FROM departments d
INNER JOIN employees e
ON d.departmentid = e.department
GROUP BY d.buildingId
For second where employees are attached to a building but it's optional. In that case LEFT JOIN is used.
SELECT b.buildingId
, COALESCE(t.count_employee, 0) count_employee
FROM building b
LEFT JOIN (SELECT d.buildingId
, COUNT(e.id) count_employee
FROM departments d
INNER JOIN employees e
ON d.departmentid = e.department
GROUP BY d.buildingId) t
ON b.buildingId = t.buildingId
If a building is attached with multiple departments and one employee is assigned with multiple departments then count building wise same employee is only onetime not multiple times. In that case DISTINCT keyword is used inside COUNT().
SELECT d.buildingId
, COUNT(DISTINCT e.id) count_employee
FROM departments d
INNER JOIN employees e
ON d.departmentid = e.department
GROUP BY d.buildingId

Writing a SQL query to return data from multiple tables

I am working through a database textbook and I am stuck on a certain exercise.
Question 6 on page 74 of the book, and a copy of the database I am working on can be found here. On page 72 you can see portions of the two tables. I want to write an SQL query that will return the name of the department, the last name of the manager/head of the department and the last name of the employees who work there.
E.g.
Marketing Herring Holt
So I have been able to print the department name, the empId of the manager and the last names of the employees with the following SQL query.
SELECT department, manager, lastName
FROM Department d
INNER JOIN Employee e
ON e.dept = d.deptId;
Use self join to get the manager-employee relationship records
SELECT d.department,
e1.lastname As Employee,
e.lastname As Manager
FROM (employee AS e
INNER JOIN department AS d
ON d.deptid = e.dept )
INNER JOIN employee AS e1
ON e1.supervisor = e.empid
EDIT: The exact solution to the question asked
SELECT d.department, m.lastName, e.lastName
FROM (employee AS e INNER JOIN department AS d ON d.deptId = e.dept)
INNER JOIN employee AS m ON d.manager = m.empId;

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);

Trying to tie the information from three different tables into one with a join query

So I have three queries I'm trying to join all on the department name field, but I don't know how to do a join on them. Each of my queries below give me some or part of the info I'm looking, but I want the information combined in one table, by department.
the first table is: (total employee count by department)
`
select d.name, count(*)
from employee e join department d
on e.dept_id = d.dept_id
group by d.name;
`
which gives me this:
Administration 3
Loans 1
Operations 14
the second is:
`
select d.name, m.emp_id
from employee e join employee m
on e.superior_emp_id = m.emp_id
join department d
on d.dept_id = e.dept_id
group by d.name, m.emp_id;
`
which gives me this (the manager id number, and which dept they work in)
Operations 3
Loans 4
Operations 6
Operations 10
Operations 13
Operations 4
Operations 16
Administration 1
and my third table:
`
select d.name, b.city
from employee e join branch b
on e.assigned_branch_id = b.branch_id
join department d
on d.dept_id = e.dept_id
group by d.name, b.city;
`
which gives me this:
Administration Waltham
Operations Waltham
Operations Woburn
Loans Waltham
Operations Quincy
Operations Salem
I want a table that just gives me the sum totals by the dept (admin, loans, operations) for the employees (the first table), the managers (total managers managing employees for each dept) and how many different branch locations each dept is located at. So the query should come back with
Dept| Staff Count | Location Count | Manager Count with their respective totals by each department.
I'm trying to figure out how to do the join query on this. Any help would be greatly appreciated.
You should be able to get the results you are looking for by using subselects
SELECT
d.Name AS Dept
,(SELECT COUNT(*)
FROM Employee e
WHERE e.dept_id = d.dept_id ) AS StaffCount
,(SELECT COUNT(*)
FROM Employee e
JOIN Branch b ON e.assigned_branch_id = b.branch_id
WHERE e.dept_id = d.dept_id GROUP BY b.city) AS LocationCount
,(SELECT COUNT(*)
FROM Employee e
JOIN Employee m ON e.superior_emp_id = m.emp_id
WHERE e.dept_id = d.dept_id GROUP BY m.emp_id) AS ManagerCount
FROM department d