1

I'm currently working with a database containing the following schema:

Schema

Here are the tasks I'm required to carry out:

tasks

For task 1, I formulated the following query (inclusion of avg(salary) was for testing purposes):

select dname, count(*), avg(salary)
from department, employee 
where dno = dnumber
group by dname having avg(salary)>30000;

giving the output:

DNAME                       COUNT(*) AVG(SALARY)
------------------------- ---------- -----------
Hardware                          10       63450
Research                           4       33250
Headquarters                       1       55000
Administration                     3       31000
Software                           8       60000
Sales                             14  40821.4286

However I can not figure out task two. **I'm required to have the same values, however only with the count of males but the same average as the previous query **. I tried the following statement:

select dname, count(*), avg(salary) 
from department, employee 
where dno = dnumber and (dno,sex) in (select dno, sex from employee where sex = 'M' ) 
group by dname having avg(salary)>30000;

Which resulted in the correct count value, but resulted in the departmental average salary for males, not males and females. As seen below:

DNAME                       COUNT(*) AVG(SALARY)
------------------------- ---------- -----------
Hardware                           7  65785.7143
Research                           3       36000
Headquarters                       1       55000
Software                           7  57285.7143
Sales                             10       42150

Please note I have to do this using nested queries, not CASE.

Hope this makes sense, any help would be appreciated.

Thanks.

3 Answers 3

2

you can do male employee count using CASE

Also converted explicit join ( comma separated tables in FROM CLAUSE) to implicit join

select D.dname, count(case when E.sex='M' then 1 else 0), avg(E.salary) 
from department D
join employee E
on E.dno = D.dnumber  
group by D.dname 
having  avg(Esalary)>30000;

As per OP comment, if this needs to be done using only nested queries, it can be done with subquery

select T.dname, count(*), T.salary as AverageSalary
FROM employee E
join ( select D.dname, D.dnumber, avg(salary) as salary 
       from employee E 
       join department D 
       on E.dno = D.dnumber 
       group by  D.dname, D.dnumber 
       having  avg(salary) > 30000 ) T
on E.sex ='M'
and E.dno = T.dnumber
group by T.dname, T.salary
Sign up to request clarification or add additional context in comments.

2 Comments

A friend did show me this way, but according to the lecturer we're required to do it using nested queries. I will clarify this in the post. I understand this is the best way to do it but it's not the way we've been told to do it. Thanks though
I'm receiving a missing key word error on line 9? AND E.sex = 'M' ?
1

This can also be done by evaluating the overall average in a subquery, derived table or cte per department before applying it to the filtered employees. Also note the preference for joining in join not in the where.

with cteSalary as
(
    select dname, dno, avg(salary) as avgSalary
    from department inner join employee on dno = dnumber
    group by dname, dno
)
select s.dname, count(e.fname), s.avgSalary
from employee e inner join cteSalary s on e.dno = s.dno
where e.sex = 'M' and s.avgSalary > 30000
group by s.dname, s.avgSalary;

Comments

0

Another solution would be this one (not tested):

with t as
   (select dname, sex,
      count(*) over (partition by dno, sex) as count_emp, 
      avg(salary) over (partition by dno) as avg_salary
   from department
      join employee on dno = dnumber)
select distinct *
from t
where avg_salary > 30000
   and sex = 'M';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.