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)
精彩评论