SQL

时间:2016-03-06 00:54:01

标签: sql oracle

我想在oracle中回答以下问题:

列出不参与任何项目的员工姓名。

使用以下代码:

select e.ename, count(w.pno) from employee e, works_on w where e.ssn=w.essn group by e.ename having count(w.pno) not in (select e.ename, count(w.pno) from works_on w, employee e where e.ssn=w.essn having count(w.pno)<>0);

但是我收到了错误 第6行的错误: ORA-00913:值太多

2 个答案:

答案 0 :(得分:1)

这是您应该使用显式joins的一个很好的例子。要这样做,您需要outer join

select e.ename
from employee e
    left join works_on w on e.ssn=w.essn
where w.essn is null

通常,最好不要在from子句中使用逗号。

以下是使用not exists

的方法
select name
from employee e
where not exists (
   select 1  
   from works_on w
   where e.ssn = w.essn
)

答案 1 :(得分:1)

您的查询抛出ORA-00913: too many values,因为NOT IN子句引用的子查询应该只返回一个值,但您将返回e.enamecount(w.pno)。如果您删除e.ename,,则会执行。

但是,它仍然不会返回任何结果,因为您试图从INNER JOIN表中查找EMPLOYEE行,该表有WORKS_ON表,您正在尝试查找员工该表中没有条目,INNER JOIN根本不会返回任何行,因为WORKS_ON中没有任何内容可以加入。

如果您将查询更改为LEFT OUTER JOIN,那么它将起作用:

select e.ename, count(w.pno)
from employee e
     LEFT OUTER JOIN works_on w
     ON e.ssn=w.essn
group by e.ename
having count(w.pno) not in
( select count(w.pno) 
  from works_on w, employee e
  where e.ssn=w.essn
  having count(w.pno)<>0);

但它效率低下,可以更简单地表达为:

SELECT   e.ename,
         count(w.pno)
FROM     employee e
         LEFT OUTER JOIN works_on w
         ON e.ssn=w.essn
GROUP BY e.ename
HAVING   count(w.pno) = 0;

(但是你遇到了一个问题,那就是你要对员工的名字进行分组,如果两个人有相同的名字,那么他们就会错误地归为一类。)

使用NOT EXISTS

可以更简单地表达,如果没有分组问题
SELECT e.ename
FROM   Employees e
WHERE  NOT EXISTS (
  SELECT 1
  FROM   Works_on w
  WHERE  e.ssn = w.essn
);