I need to get number of employees per depatment - sql

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

Related

Complex query - retrieve employees working in both two specific departments

I'm trying to figure a way to retrieve employees working in two different departments.
I have 3 simple tables:
employee (employee_id, employee_name)
department (department_id, department_name)
working (eid, did, work_time)
So I have tried to write a SQL query:
select employee_name
from employee, working,department
where eid = employee_id
and did = department_id
and department_name = 'software'
and dname = 'hardware';
But it doesn't work, what is my problem?
The problem is that you are requiring department to be both 'software' and 'hardware'. Also, dname is not a field.
Correcting your query:
select employee_name
from employee, working, department
where eid = employee_id and did = department_id
and (department_name = 'software' or department_name = 'hardware');
But I would prefer this kind of query:
SELECT DISTINCT e.employee_name
FROM employee e
JOIN working w ON w.eid = e.employee_id
JOIN department d ON d.department_id = w.did
WHERE d.department_name IN ('software', 'hardware');
That is to get employees that work in any of the two departments (or both).
If you want only employees that work in both departments, try this:
SELECT e.employee_id, e.employee_name
FROM employee e
JOIN working w ON w.eid = e.employee_id
JOIN department d ON d.department_id = w.did
WHERE d.department_name IN ('software', 'hardware')
GROUP BY e.employee_id HAVING COUNT(DISTINCT d.department_id) = 2;
Would something like this work for you?
SELECT
count(*) as cnt,
employee.employee_name
FROM
employee
JOIN working ON working.eid = employee.employee_id
JOIN department ON department.department_id = working.did
WHERE
department.department_name = 'software' or department.department_name = 'hardware'
GROUP BY employee.employee_name
HAVING cnt > 1
This would count each employee who is linked both software or hardware department. Or you can leave WHERE clause away to get all employees working more than one departments.
What is my problem?
There is no dname column in your tables.
You can simplify the problem as you don't need the department table since the working table contains the department id in the did column.
Then you need to GROUP BY each employee and find those HAVING a COUNT of two DISTINCT department ids:
SELECT MAX(e.employee_name)
FROM employee e
INNER JOIN working w
ON e.employee_id = w.eid
GROUP BY e.employee_id
HAVING COUNT(DISTINCT w.did) = 2
If you want to consider only the software and hardware departments then:
SELECT MAX(e.employee_name)
FROM employee e
INNER JOIN working w
ON e.employee_id = w.eid
INNER JOIN department d
ON w.did = d.department_id
WHERE d.department_name IN ('software', 'hardware')
GROUP BY e.employee_id
HAVING COUNT(DISTINCT w.did) = 2
You can easily obtain employees who work in one specific department:
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = 'software'
Now ambiguity cames. If you want to get all employees work either in software or in hardware:
-- Employees who work at either software or hardware or both departments
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = in ('software', 'hardware')
If you want to get employees who works in both software and hardware departments:
-- Employees who work in both hardware and software deparments simultaneously
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = 'software'
intersect
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = 'hardware'

How to get the average score of a department using sql

I want to get the average score of all department in my database, I have a query that get the average score of just one department, is there a way I can get the name of the department and their average score.
Lets assume I have 2 departments(Server and IT), The average of the server is the sum of all score of the people in that department divided by the total number of the department.
Here is a query I Have, but it's just the average of one department
SELECT SUM(RatingId)/(select COUNT(Id) from Employee where DepartmentId = 5) as Sums
FROM PerformanceReviewRatings pfr join
Employee e
on pfr.EmployeeId = e.Id join
Department d
on d.Id = e.DepartmentId
WHERE pfr.AppraisalId = 1009;
Use group by
SELECT e.DepartmentId, d.name,
SUM(RatingId)/COUNT(1) as Sums
FROM PerformanceReviewRatings pfr
JOIN Employee e
ON pfr.EmployeeId = e.Id
JOIN Department d
ON d.Id = e.DepartmentId
WHERE pfr.AppraisalId = 1009
GROUP BY e.DepartmentId, d.name
Assuming an employee gets only one rating, you don't need a subquery or a reference to the Department table:
SELECT e.DepartmentId,
SUM(RatingId)/COUNT(*) as average_rating
FROM Employee e LEFT JOIN
PerformanceReviewRatings pfr
ON pfr.EmployeeId = e.Id AND
pfr.AppraisalId = 1009
GROUP BY e.DepartmentId;
If you only want the average of employees with ratings -- rather than one your question asks (which is to treat unrated employees as 0s -- then:
SELECT e.DepartmentId, AVG(RatingId) as average_rating
FROM Employee e JOIN
PerformanceReviewRatings pfr
ON pfr.EmployeeId = e.Id
WHERE pfr.AppraisalId = 1009
GROUP BY e.DepartmentId
Using the AVG() function.
SELECT e.DepartmentId,
AVG(RatingId) as average_rating
FROM Employee e LEFT JOIN
PerformanceReviewRatings pfr
ON pfr.EmployeeId = e.Id AND
pfr.AppraisalId = 1009
GROUP BY e.DepartmentId

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

SQL group functions using joins

Problem:
Create a list of department names, the manager id,
manager name (employee last name) of that department, and the average salary in each
department.
SELECT d.department_name, d.manager_id, AVG(e.salary)
FROM employees e
INNER JOIN departments d ON (e.department_id = d.department_id)
GROUP BY d.department_name, d.manager_id;
And it works nice, but when I add the e.last_name, I get all the last names from employees table.
I do believe the answer to be out here and not quite far, although out of my reach at this point.
In order to pull the name of the manager, you need to join employees again, this time on d.manager_id:
SELECT d.department_name, d.manager_id, m.name, AVG(e.salary)
FROM employees e
INNER JOIN departments d ON (e.department_id = d.department_id)
LEFT OUTER JOIN employees m ON (m.employee_id = d.manager_id)
GROUP BY d.department_name, d.manager_id, m.name;
The kind of join (inner or outer) is not essential here, because you group by d.manager_id.
It looks like you need to join d.manager_id to employees again to get the managers last_name:
SELECT d.department_name, d.manager_id, e2.last_name, AVG(e.salary)
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
INNER JOIN employees e2 ON d.manager_id = e2.employee_id
GROUP BY d.department_name, d.manager_id, e2.last_name

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