Join 3 tables and Group - sql

I am stuck here working on a homework and this is what I have got.
Instruction is: Display department name, city and number of different jobs in each department.
tables employees (has job_id and department_id), deptos (has location_id, department_id but no job ids), locations (has location_id and city)
I need to include all cities even the ones without employees
What I was trying to do...
select d.department_name, l.city, count (distinct e.job_id)
from employees e
join deptos d on (e.department_id=d.department_id)
join locations l on (d.location_id=l.location_id)
group by d.department_name

locations can have data missing in other tables, so right join or you start from it and use left joins. You also need to group by city. Tried to do minimum changes to OP query.
select d.department_name, l.city, count(distinct e.job_id)
from employees e
join deptos d on (e.department_id=d.department_id)
right join locations l on (d.location_id=l.location_id)
group by d.department_name, l.city
SQL Fiddle to test with

You need to use a OUTER JOIN to accomplish this... like the below. You do not necessarily have to use the keyword outer as it is implied, just remember the the difference between using LEFT and RIGHT joins there is a post on that here. Example below
LEFT JOIN vs. LEFT OUTER JOIN in SQL Server
select d.department_name, l.city, count (distinct e.job_id)
from locations l
left outer join deptos d on (e.department_id=d.department_id)
left outer join employees e on (d.location_id=l.location_id)
group by d.department_name

SELECT locations.city, deptos.department_name,
Count(DISTINCT employees.job_id) AS DiffJobsDeptCount
FROM employees
RIGHT JOIN (deptos
RIGHT JOIN locations
ON deptos.location_id = locations.location_id)
ON employees.department_id = deptos.department_id
GROUP BY locations.city, deptos.department_name

Related

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

Right outer JOIN in SQL

I have to list all departments, which do not have any employees assigned to but I don't know how to solve this with a outer-join. The scheme of the database is:
My current statement is
SELECT DISTINCT d.department_name
FROM departments d
RIGHT OUTER JOIN employees e ON NOT e.department_id IS NULL;
but it doesn't work as it should.
My result is this:
It should look like this:
Does anybody know what's wrong?
You can right this as an outer left join like so, correlating on the department_id
SELECT d.department_name
FROM departments d
LEFT JOIN employees e ON e.department_id=d.department_Id
WHERE e.employee_id is null
Or a more intuitive version would be where there does not exist any employees for a department_id
SELECT d.department_name
FROM departments d
WHERE NOT EXISTS (SELECT * FROM employees e WHERE e.department_id=d.department_Id )

MySQL LEFT JOIN with GROUP BY and WHERE clause query

Tables that look like bellow
How to write SQL Query to read all department names with an employee count salary > 1000, if a department not found in employee we required to show as zero counts in output.
You can use left join and aggregation:
select d.name, count(e.id)
from departments d left join
employees e
on e.department_id = d.id and e.salary >= 10000
group by d.name

Oracle sql scripting. Querying. List the locations the company has employees located at

Hey I am struggling with a question, I am a beginner at database management. I have the following database, and I want to make this query: List the locations the company has employees located at and how many employees are at each location ordered by the location with the most employees in descending
Anybody help please!
this is the database
I believe this gets what you're looking for.
Select l.location_id, c.country_name, count(e.employee_id) as employee_count
From locations l
left join countries c ON c.country_id = l.country_id
left join departments d ON l.location_id = d.location_id
left join employees e ON e.manager_id = d.manager_id
GROUP BY l.location_id, c.country_name
ORDER BY employee_count DESC;

Subquery using 3 Tables SQL

I'm trying to display the last name of the lowest paid employees from each city. The city column falls under a table titled LOCATIONS while employee information(salary, last name) falls under EMPLOYEES. Both of these tables are related share no common table, so I have to rely on a third table, DEPARTMENTS to connect the two as DEPARTMENTS contains a department_id that it shares with EMPLOYEES as well as a LOCATION_ID that it shares with LOCATIONS. This is what I have so far, but I'm having trouble with this as I've mostly worked with only two tables in the past.
SELECT LAST_NAME
FROM EMPLOYEES
WHERE (DEPARTMENT_ID) IN
(SELECT DEPARTMENT_ID
FROM DEPARTMENTS
WHERE LOCATION_ID IN
(SELECT LOCATION_ID
FROM LOCATIONS
GROUP BY CITY
HAVING MIN(SALARY)));
This seems to be an assignment in an intro course in SQL. So let's assume you can't use analytic functions, match_recognize clause, etc. Just joins and aggregates.
In the subquery in the WHERE clause below, we compute the min salary for each city. We need to join all three tables for this. Then in the overall query we join the three tables again, and we use the subquery for an IN condition (a semi-join). The overall query looks like this:
select e.last_name
from employees e join departments d
on e.department_id = d.department_id
join locations l
on d.location_id = l.location_id
where ( e.salary, l.city ) in
(
select min(salary), city
from employees e join departments d
on e.department_id = d.department_id
join locations l
on d.location_id = l.location_id
group by city
)
;
You should separate out the concept of table joins from WHERE clauses.
Use WHERE for filtering data, use JOIN for connecting data together.
I think this is what you are wanting. By the way, lose the ALL CAPS if you can.
SELECT
LAST_NAME
FROM
EMPLOYEES
INNER JOIN (
SELECT
DEPARTMENTS.DEPARTMENT_ID,
CITY,
MIN(SALARY) AS LOWEST_SALARY
FROM
EMPLOYEES
INNER JOIN DEPARTMENTS ON EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
INNER JOIN LOCATIONS ON DEPARTMENTS.LOCATION_ID = LOCATIONS.LOCATION_ID
GROUP BY
DEPARTMENTS.DEPARTMENT_ID,
LOCATIONS.CITY
) AS MINIMUM_SALARIES
ON EMPLOYEES.DEPARTMENT_ID = MINIMUM_SALARIES.DEPARTMENT_ID
AND EMPLOYEES.SALARY = MINIMUM_SALARIES.LOWEST_SALARY
First of all join the tables, so you see city and employee in one row. If we group by city we get the minimum salary per city.
with city_employees as
(
select l.city, e.*
from locations l
join departments d using (location_id)
join employees e using (department_id)
)
select last_name
from city_employees
where (city, salary) in
(
select city, min(salary)
from city_employees
group by l.city
);
It is easier to achieve the same, however, with window functions (min over or rank over here).
select last_name
from
(
select
e.last_name,
e.salary,
min(e.salary) over (partition by l.city) as min_salary
from locations l
join departments d using (location_id)
join employees e using (department_id)
)
where salary = min_salary;