简体   繁体   中英

Oracle: single-row subquery returns more than one row

SELECT e.name from emp e, departm d, salery s WHERE e.dep=d.depid AND s.emp= e.empid AND s.sal > (SELECT round(avg(s.sal)) as AVGSAL from emp e, departm d, salery s WHERE e.dep=d.depid AND s.emp= e.empid GROUP BY d.depid );

MY Tables are: emp (empid, name, dep) departm (depid, name, headdep) salery (emp, cost, sal, fdate)

I have some foreign keys:
departm: FOREIGN KEY (headdep) REFERENCES departm(depid)
emp: FOREIGN KEY(dep) REFERENCES departm(depid)
salery: FOREIGN KEY(emp) REFERENCES emp(empid)

I want to print a list of all employees which earn more money than the average of theyr department but when i run this query i have an error: single-row subquery returns more than one row

Can anyone help me? What's the problem with my query? Finally I want to create a procedure, but first of all i have to write the query.

Thank you guys...

Analytic functions are the way to go on this query, but your version has several problems. You would see these problems much more readily if you used proper join syntax. You seem to be learning SQL, so just remember one simple rule: NEVER use commas in from clauses.

Apart from the syntax problem, you have a problem with your correlated subquery. Here is a version that should work:

SELECT e.vollername
from emp e join
     salery s
     on s.emp= e.empid
WHERE s.sal > (select round(avg(s2.sal)) as AVGSAL
               from emp e2 join
                    salery s2
                    on s2.emp= e2.empid 
               where e2.dep = e.depid
              );

Note the removal of the departm table from both the inner and the outer queries. In the outer one, it was merely superfluous. In the inner one, it prevented the query from producing the correct results because it removed the correlation.

This is somewhat easier with analytic functions (I also removed the join with departm , since it is not needed):

SELECT e.vollername
FROM (
  SELECT 
    e.vollername, 
    s.sal,
    round(avg(s.sal) over (partition by e.dep)) as avg_dep_sal
  FROM 
    emp e
  JOIN salery s ON e.empid = s.emp
)
where sal > avg_dep_sal

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM