Boolean inside SELECT - help needed - sql

I need to write a SQL query to get the department name and the number of female professors in that department even if there aren't any female professors hired there. Please help. Thank you.
STUDENT
id
first_name
last_name
is_female
department_id
DEPARTMENT
id
name
PROFESSOR
id
first_name
last_name
is_female
department_id
This is my query:
SELECT
department.name, COUNT(professor.is_female)
FROM
department, professor
WHERE
department.id = professor.department_id

Not sure why you included the student table but try either this correlated sub-query:
select name, (select count(*) from PROFESSOR where DEPARTMENT.id = PROFESSOR.department_id and is_female = true) as 'count'
from DEPARTMENT
or left-join:
select name, count(*)
from DEPARTMENT
left join PROFESSOR on DEPARTMENT.id = PROFESSOR.department_id and is_female = true
group by 1

Related

How to get column value from "nested relation" in sql

Not sure of the correct phrasing to use here, but here's the case.
I have 3 tables.
Employee
id
name
department_id
1
Jon Doe
2
Department
id
name
office_id
2
Accounting
3
Office
id
name
3
London
Now, getting the employee with department name is straight forward:
select employee.id, employe.name, department.name as department_name, department.office_id
from employee
inner join department on employee.department_id = department.id
How can i also include the office name in the result?
You can use a second inner join for the office:
select employee.id, employe.name, department.name as department_name, department.office_id, office.name as office_name
from employee
inner join department on employee.department_id = department.id
Inner join office on office.id = department.office_id

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

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

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

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)

Inner Join: Is this an optimal solution?

T1: employee [id, salary]
T2: department [name, employeeid]
(employeeid is a foreign key to T1's id)
Problem: Write a query to fetch the name of the department which receives the maximum salary.
My Solution:
SELECT DISTINCT name
FROM department AS a
INNER JOIN employee AS b ON a.employeeid = b.id
AND b.salary
IN (
SELECT max( salary )
FROM employee AS c
)
Edit: The problem statement is accurate, and we're not trying to find out the employee who has the highest salary. It says "....Department which receives.....", not "...employee who receives....".
Is this ok? Or can this be optimized?
GROUP BY the name of the department and order by SUM(salary).
SELECT department.name
FROM department
JOIN employee ON department.employeeid = employee.id
GROUP BY department.name
ORDER BY SUM(salary) DESC
LIMIT 1
How about:
SELECT employee.id, employee.salary, department.name
FROM department, employee
where
employee.id = department.employeeid and
employee.salary = (select max(salary) from employee)