How to get the department name in this tutorial sql query? - sql

Following the tutorial on SQL here I want to query the number of employees per department together with the department name.
I tried the following query in that tutorial:
SELECT count(*), dept_name
FROM employees, departments
WHERE employees.dept_id = departments.dept_id
GROUP BY departments.dept_id
but it returns
COUNT(*) dept_name
2 NULL
2 NULL
instead of the expected output
COUNT(*) dept_name
2 Accounting
2 Sales
What am I doing wrong here?

First use JOIN instead of WHERE
Then you group by dept_id to make sure you dont have duplicate name like 2 Sales department or 2 employee with same name.
SELECT departments.dept_id, dept_name, count(*)
FROM employees
JOIN departments
ON employees.dept_id = departments.dept_id
GROUP BY departments.dept_id, departments.dept_name

Group by dept_name not dept_id
SELECT count(*), dept_name
FROM employees, departments
WHERE employees.dept_id = departments.dept_id
GROUP BY departments.dept_name
And you can better use join like Juan Carlos Oropeza's answer:
SELECT count(*), dept_name
FROM employees JOIN departments ONemployees.dept_id = departments.dept_id
GROUP BY departments.dept_name

Related

SQL MAX((SUM)) combined usage

I have two tables:
EMPLOYEE: ID|DEPARTMENT_ID|CHIEF_ID|NAME|SALARY
DEPARTMENT: ID|NAME
The task here is to get list of departments with total max salary of all employees.
The query I'm trying to use (completes with no results):
SELECT s.DEPARTMENT_ID, s.SALARY_SUM
FROM (SELECT DEPARTMENT_ID, SUM(SALARY) SALARY_SUM, w.ID
FROM EMPLOYEE e
JOIN DEPARTMENT w ON w.ID = e.DEPARTMENT_ID
GROUP BY e.DEPARTMENT_ID, w.ID) s
WHERE s.SALARY_SUM = (SELECT MAX(SALARY) MaxSum
FROM EMPLOYEE w1
WHERE w1.ID = s.ID)
This will get you all the Deoatnent that have the highest Sum from their employees
CREATE tABLe EMPLOYEE(DEPARTMENT_ID INT, SALARY INT)
GO
CREATE TABLe DEPARTMENT(ID int)
GO
WITH CTE as (SELECT DEPARTMENT_ID, SUM(SALARY) SALARY_SUM, w.ID
FROM EMPLOYEE e
JOIN DEPARTMENT w ON w.ID = e.DEPARTMENT_ID
GROUP BY e.DEPARTMENT_ID, w.ID)
SELECT s.DEPARTMENT_ID, s.SALARY_SUM
FROM CTE s
WHERE s.SALARY_SUM = (SELECT MAX(SALARY_SUM) MaxSum
FROM CTE w1 )
GO
DEPARTMENT_ID | SALARY_SUM
------------: | ---------:
db<>fiddle here
You essentially have 4 data sets here.
EMPLOYEE e
DEPARTMENT w
Subquery1 s
Subquery2 (where clause)
Data set 3 has salary aggregated by Department ID.
Data set 4 has the largest employee salary for each department.
The Where clause is saying compare 3 to 4 where SALARY_SUM = MaxSum. Because SALARY_SUM is aggregated by Department ID, and MaxSum is the largest individual salary, this where clause will only return results for departments with 1 person (or if people have a salary of $0).
If a department has multiple people with salaries, the SUM of the department's salary will always be greater than the largest individual salary in the department.

Write a query to display the name of the department that has the maximum student count

this is the schema Write a query to display the name of the department that has the maximum student count.
this is what is tried.
select d.department_name,count(s.student_id)
from department d left join student s
on d.department_id=s.department_id
group by d.department_name,d.department_id
order by d.department_name;
and i think there is something missing in my code
You're almost there.
Order the result in descending order on the number of students and then take the first row:
SELECT department_name
FROM
(
SELECT d.department_name,
COUNT(*) AS nr_students
FROM department d
JOIN student s
ON d.department_id = s.department_id
GROUP BY d.department_name
ORDER BY nr_students DESC
)
WHERE ROWNUM <= 1;
Based on the schema mentioned, you would have to make a join (INNER JOIN) to the department table from the staff table to get the name of the department.
If the name of the department is not desired and the counts can just be based on the department_id, then a join is not required.
The queries for both the scenarios is mentioned below.
Oracle SQL query for result with the department name, i.e. with INNER JOIN
SELECT D.DEPARTMENT_NAME, COUNT(S.DEPARTMENT_ID) AS STAFF_COUNT FROM **DEPARTMENT D, STAFF S** --INDICATES INNER JOIN IN ORACLE SQL
WHERE D.DEPARTMENT_ID = S.DEPARTMENT_ID
GROUP BY D.DEPARTMENT_NAME
ORDER BY STAFF_COUNT DESC
Oracle SQL query for result without the department name, just the department_id
SELECT S.DEPARTMENT_ID,COUNT(S.DEPARTMENT_ID) AS STAFF_COUNT FROM STAFF S
GROUP BY S.DEPARTMENT_ID
ORDER BY STAFF_COUNT DESC
Hope this helps. Cheers.
I tried this and it worked.
select department_name
from department d inner join student s
on s.department_id=d.department_id
having count(*) in (
select max(count(student_id))
from student s join department d
on d.department_id=s.department_id
group by d.department_id)
group by d.department_id,department_name;
Select * from (
SELECT D.DEPARTMENT_NAME, COUNT(S.DEPARTMENT_ID) AS STAFF_COUNT
FROM DEPARTMENT D, STAFF S
WHERE D.DEPARTMENT_ID = S.DEPARTMENT_ID
GROUP BY D.DEPARTMENT_NAME
ORDER BY STAFF_COUNT DESC)
where rownum=1;
This query will give department name that has maximum number of student count

Simple SQL query not working out

click here for database model
Asked: Show for every department with at least 3 employees, the department's name and the amount of employees in that department born before 1967.
My code so far:
`Select department, department_name, numberofemployeesbefore1967 = ( select count(empleyee_id) from employee where year(dateofbirth) < 1967)
From employee inner join department on (department = department_id)
group by department, department_name
having count(*) >=3`
The output I have now: output
I feel like this is a really easy one, but I cannot find how to show only the employees born before 1967 for that specific department.
Anyone to help me out?
I check the year in the main query and >=3 in a subquery
SELECT department department_name, count(*)
FROM department d
JOIN employee e on d.department_id = e.department
WHERE YEAR(dateOfBirth) < 1967
AND (SELECT COUNT(*) FROM employee WHERE department = d.department_id) >= 3
GROUP BY d.id, d.name
Tweaked the subquery like so...
Select department, department_name, (select count(empleyee_id) from employee where year(dateofbirth) < 1967) AS numberofemployeesbefore1967
From employee inner join department on (department = department_id)
group by department, department_name
having count(*) >=3

SQL Query on Instructor table

I am stuck at the following SQL query:
Find the name of the departments having more than 12 instructors.
Ans should be given according to the given diagram.
Should be something like this:
select dept_name
, count(ID)
from instructor
group by dept_name
having count(ID) > 12
use the group by and having clauses to filter on an aggregation function.
select d.dept_name
from department d
inner join instructor i
on i.dept_name = d.dept_name
group by d.dept_name
having count(*) > 12

Get MAX element based on two different tables

I have problem with SQL query on Oracle DB.. I have following tables:
DEPARTMENT(`ID` NUMBER(11), `NAME` VARCHAR(25))
EMPLOYEE(`ID` INT(11), `LASTNAME` VARCHAR(25), `DEP_ID` INT(11));
SALARIES(`ID` INT(11), `EMPLOYEE_ID` INT(11), `SALARY` INT(11));
Now, I want to get name of depratment with highest average sum of salary. Department isn't directly related to Salaries so probably I need to use Employee table as well.
I've created a query:
SELECT NAME, (SELECT SUM(SALARIES.SALARY) FROM SALARIES JOIN EMPLOYEE ON EMPLOYEE.EMPLOYEE_ID = EMPLOYEE.ID WHERE EMPLOYEE.DEP_ID = DEPARTMENT.ID GROUP BY EMPLOYEE.ID) AS AVG_OF_SUM FROM DEPARTMENT;
It returns list of department's name and avg sum. But now I need to get only one department name for the highest averange row.
Is my query actually OK? Or can be improved? And how can I get only one record?
Thanks for any help.
Regards,
D
Make use of the ANALYTIC function SUM...OVER
In the subquery, apply the analytic function, and then select only those rows which you desire.
For example,
SELECT DISTINCT DEPT, SUM(SAL) OVER (PARTITION BY DEPT ORDER_BY DEPT) SUM_SAL
FROM EMPLOYEE
ORDER_BY DEPT;
SELECT NAME, (SELECT MAX(SUM(SALARIES.SALARY))
FROM SALARIES
JOIN EMPLOYEE ON EMPLOYEE.EMPLOYEE_ID = EMPLOYEE.ID )
WHERE EMPLOYEE.DEP_ID = DEPARTMENT.ID
GROUP BY EMPLOYEE.ID) AS AVG_OF_SUM FROM DEPARTMENT;
SELECT NAME, avg_sal FROM
(SELECT d.NAME, avg(s.SALARY) avg_sal
FROM SALARIES s
JOIN EMPLOYEE e ON s.EMPLOYEE_ID = e.ID
JOIN DEPARTMENT d ON e.DEP_ID = d.ID
GROUP BY d.NAME
ORDER BY 2 DESC)
WHERE rownum = 1;
(This query shows a department with the highest avg salary. If you need sum replace AVG -> SUM)