开发者

Single-row subquery returns more than one row

I need some help with oracle sql. The problem: I have 2 tables employee and department. I got the average department salary from one query and i want to use it to see how many employees make more money than the average of their department. I have this so far.

This query returns the avg of the department:

select ROUND(AVG(Salary), 2) Dept_avg_sal
 from employee, department
 where department.department_id = employee.department_id
 group by department_name

What i am try开发者_如何学编程ing to do is:

select employee_name,
       salary,
       d.department_name
from   employee e,
       department d
where  salary > (select ROUND(AVG(Salary), 2) Dept_avg_sal
                 from   employee,
                        department
                 where  department.department_id = employee.department_id
                 group  by department_name)  

The error that im getting is :01427. 00000 - "single-row subquery returns more than one row"

I know that 2 employees in the same department make more money than the average and i think this is what is causing the issue.

EMPLOYEE_NAME       - SALARY -                -DEPARTMENT_NAME-      DEPT_AVG_SAL           
-------------------- ---------------------- -------------------- ------------ 
FISHER              - 3000.00  -              SALES      -          2500.00                   
JONES          -      3000.00               - ACCOUNTING         -  2750.00                   
KING             -    5000.00           -     EXECUTIVE     -       4500.00                   
**SCOTT           -     2500.00           -     IT             -      2100.00                   
SMITH           -     2900.00          -      IT     -              2100.00**                   
WILSON           -    3000.00          -      RESEARCH      -       2633.33 

Any help would be really appreciated.


Your initial query is missing any join condition on the outer query and any correlation condition in the inner query that would limit that to just the row for the department of interest. Also generally you do not want to group by name as presumably id is the primary key.

Resolving these issues to fix your correlated subquery gives

SELECT e.employee_name,
       e.salary,
       d.department_name
FROM   employee e
       JOIN department d
         ON d.department_id = e.department_id
WHERE  e.salary > (SELECT ROUND(AVG(Salary), 2) Dept_avg_sal
                   FROM   employee e2
                   WHERE  e2.department_id = e.department_id)  

But you may find ditching the scalar correlated sub-query and replacing with a derived table works better.

SELECT e.employee_name,
       e.salary,
       d.department_name
FROM   employee e
       JOIN department d
         ON d.department_id = e.department_id
       JOIN (SELECT ROUND(AVG(Salary), 2) Dept_avg_sal,
                    department_id
             FROM   employee
             GROUP  BY department_id) e2
         ON e2.department_id = e.department_id
            AND e.salary > e2.Dept_avg_sal  

For Oracle the following should also work I believe

SELECT employee_name,
       salary,
       d.department_name
FROM   (SELECT employee_name,
               salary,
               d.department_name,
               AVG(Salary) OVER (PARTITION BY e.department_id) AS AvgSalary
        FROM   employee e
               JOIN department d
                 ON d.department_id = e.department_id)
WHERE  salary > AvgSalary  


The > operator accepts only one value, thus your inner SELECT has to return exactly 1 row. My guess is that you get multiple rows. Look at what your inner SELECT returns and try LIMIT 1.


I think you should put an extra d.department_id = department.department_id condition to the subquery (not tested):

select employee_name,
       salary,
       d.department_name
from   employee e,
       department d
where  salary > (select ROUND(AVG(Salary), 2) Dept_avg_sal
                 from   employee,
                        department
                 where  department.department_id = employee.department_id 
                 AND d.department_id = department.department_id
                 group  by department_name)  

Or just write:

select e.employee_name,
       e.salary,
       d.department_name
from   employee e,
       department d
where  e.department_id = d.department_id
       AND salary > (select ROUND(AVG(Salary), 2) Dept_avg_sal
                 from employee
                 where e.department_id = employee.department_id)  
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜