Find the number of employees in each department using rollup - sql

so i use code like this:
select count(*) as count, d.department_name
from employees e inner join departments d on e.department_id = d.department_id
group by d.department_name;
but I want to add a rollup function, how do I do it?

Like this:
SELECT COUNT (*) AS COUNT, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
GROUP BY ROLLUP (d.department_name);

Related

Select EVERY department and number of employees with salary higher than 10000

I need to select every department name and number of employees earning 10000 or more. That's my code.
SELECT d.department_name, COUNT(e.employee_id)
FROM hr.employees e
JOIN hr.departments d ON d.department_id=e.department_id WHERE e.salary > 10000
GROUP BY d.department_name;
It shows only departments which contains employees earning 10000 but I also need rest of departments with number 0 or - in column COUNT(e.employee_id). Can you help me?
You can do conditional aggregation. The idea is to not put the condition on employee salary in the join, but instead it in a conditional sum:
select
d.department_name,
sum(case when e.salary > 10000 then 1 else 0 end) cnt_high_salaries
from hr.department d
inner join hr.employee e on d.department_id = e.department_id
group by d.department_id, d.department_name
I think you just need outer join in your original query.
SELECT d.department_name,
COUNT(e.employee_id)
FROM hr.departments d
LEFT JOIN hr.employees e
ON d.department_id=e.department_id
and e.salary > 10000
GROUP BY d.department_name;
Is this what you are looking for?
SELECT d.department_name, COUNT(e.employee_id) FROM hr.employees e
JOIN hr.departments d ON d.department_id=e.department_id WHERE d.department_id in
(SELECT distinct e.department_id from employees e WHERE e.salary > 10000)
GROUP BY d.department_name;

Is it possible to retrieve number of departments and the number of employees working in that department if given the location Id

Is it possible to retrieve the number of departments and the number of employees working in that department if given the location Id? Location_id column is in the departments table. Employees and Department share department_id column
Cannot get the correct result with this query:
select
count(E.employee_id), count(D.DEPARTMENT_ID)
from
employees e
join
departments d on (e.department_id = d.department_id)
where
D.LOCATION_ID = 1700;
I suspect you need distinct when counting the departments:
SELECT
COUNT( E.employee_id )
, COUNT(DISTINCT d.department_id )
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE d.location_id = 1700;
or, you need to group by department:
SELECT
COUNT( E.employee_id )
, d.department_id
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE d.location_id = 1700
GROUP BY d.department_id;

"Group by" expression

I have some problems trying to print department_id, department_name and the sum of salaries of each department and I can't figure out why. I get the error: 00979 - "not a GROUP BY expression"
SELECT d.department_id, d.department_name, SUM(e.salary)
FROM departments d, employees e
WHERE d.department_id = e.department_id
GROUP BY d.department_id;
Just add the name to the group by expression. Along the way, also fix the query to use explicit join syntax:
SELECT d.department_id, d.department_name, SUM(e.salary)
FROM departments d JOIN
employees e
ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;
Although you didn't ask, I will point out that your version of the query does make sense and is ANSI-compliant (although most databases don't support this feature). You are aggregating by a primary key, so bringing in additional columns is allowed -- although Oracle does not support this feature.
SELECT d.department_id, d.department_name, SUM(e.salary)
FROM departments d, employees e
WHERE d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;
Just needed to add the department_name column in your group by clause.
Alternately, you can aggregate the department name as well using MIN() or MAX():
SELECT d.department_id, MAX(d.department_name) AS department_name
, SUM(e.salary) AS department_salary
FROM departments d INNER JOIN employees e
ON d.department_id = e.department_id
GROUP BY d.department_id;
Note that I updated your syntax from the old ANSI standard to the newer one. If you prefer the older syntax (as I do), then just use this:
SELECT d.department_id, MAX(d.department_name) AS department_name
, SUM(e.salary) AS department_salary
FROM departments d, employees e
WHERE d.department_id = e.department_id
GROUP BY d.department_id;

Two aggregation functions group by

I'm trying to print the department names that have the sum of all salaries bigger than the average sum on departments.
SELECT d.department_name, SUM(e.salary)
FROM departments d, employees e
WHERE d.department_id = e.department_id
GROUP BY d.department_name
HAVING SUM(e.salary) > (SELECT AVG(SUM(salary)) from employees);
In the second select, after what do I have to group by AVG(SUM(salary))?
You need to repeat the first query in the condition. This can be done with the WITH clause.
WITH dept_sums AS (SELECT d.department_name, SUM(e.salary) sum_salary
FROM departments d, employees e
WHERE d.department_id = e.department_id
GROUP BY d.department_name)
SELECT * FROM dept_sums d_s_1 WHERE d_s_1.sum_salary > (SELECT AVG(sum_salary) FROM dept_sums d_s_2);
This is where window (analytic) functions come in handy. Below I am using AVG() as an analytic function to calculate the average total salary across all departments.
SELECT department_name, dept_salary FROM (
SELECT d.department_name, SUM(e.salary) AS dept_salary
, AVG(SUM(e.salary)) OVER ( ) AS avg_dept_salary
FROM departments d INNER JOIN employees e
ON d.department_id = e.department_id
GROUP BY d.department_name
) WHERE dept_salary > avg_dept_salary;

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