Однорядный подзапрос возвращает более одной строки - PullRequest
2 голосов
/ 12 сентября 2011

Мне нужна помощь с оракулом sql.Проблема: у меня 2 столика сотрудника и отдела.Я получил среднюю зарплату отдела по одному запросу, и я хочу использовать ее, чтобы увидеть, сколько сотрудников зарабатывают больше денег, чем в среднем по их отделу.У меня есть это до сих пор.

Этот запрос возвращает среднее значение отдела:

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

Что я пытаюсь сделать, это:

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)  

Ошибка, котораяя получаю это: 01427.00000 - «однорядный подзапрос возвращает более одной строки»

Я знаю, что 2 сотрудника в одном отделе зарабатывают больше, чем в среднем, и я думаю, что это является причиной проблемы.

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 

Буду признателен за любую помощь.

Ответы [ 3 ]

7 голосов
/ 12 сентября 2011

В вашем исходном запросе отсутствуют какие-либо условия соединения во внешнем запросе и любые условия корреляции во внутреннем запросе, которые ограничивают его только строкой для интересующего отдела.Также обычно вы не хотите group by name, поскольку предположительно id является первичным ключом.

Решение этих проблем для исправления вашего коррелированного подзапроса дает

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)  

Но вы можете обнаружить, что исключение скалярного коррелированного подзапроса и замена производной таблицей работают лучше.

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  

Для Oracle, на мой взгляд, должно работать и следующее:

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  
1 голос
/ 12 сентября 2011

Я думаю, что вы должны поставить дополнительное условие d.department_id = department.department_id для подзапроса (не проверено):

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)  

Или просто написать:

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)  
1 голос
/ 12 сентября 2011

Оператор> принимает только одно значение, поэтому ваш внутренний SELECT должен возвращать ровно 1 строку. Я предполагаю, что вы получите несколько строк. Посмотрите, что возвращает ваш внутренний SELECT, и попробуйте LIMIT 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...