Oracle SQL嵌套语句问题

时间:2014-10-21 19:57:19

标签: sql oracle

我目前正在使用包含以下架构的数据库:

Schema

以下是我需要执行的任务:

tasks

对于任务1,我制定了以下查询(包含avg(​​薪水)用于测试目的):

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

给出输出:

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

然而,我无法弄清楚任务二。 **我需要具有相同的值,但仅限于男性的数量,但与上一个查询的平均值相同**。我尝试了以下声明:

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;

这导致了正确的计数值,但导致了男性的部门平均工资,而不是男性和女性。如下所示:

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

请注意我必须使用嵌套查询,而不是CASE。

希望这是有道理的,任何帮助都会受到赞赏。

感谢。

3 个答案:

答案 0 :(得分:2)

您可以使用CASE

进行男性员工人数统计

还将显式连接(FROM CLAUSE中的逗号分隔表)转换为隐式连接

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;

根据OP注释,如果需要仅使用嵌套查询来完成,则可以使用子查询来完成

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

答案 1 :(得分:1)

这也可以通过在将子查询,派生表或每个部门的cte应用于过滤员工之前评估总体平均值来完成。另请注意,加入join的偏好不在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;

答案 2 :(得分:0)

另一个解决方案是这个(未经测试):

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';