在SQL查询中使用“AND”和“OR”

时间:2012-10-05 06:11:10

标签: sql oracle

我有以下表格

  • 学生(sid,sname,年龄)
  • 当然(cid,cname,duration)
  • 注册(sid,cid,date)

查找使用java rdbms

的学生的sids
select sid 
from enroll e, 
     course c 
where (c.cname like 'java' and c.cid=e.cid) 
   or (c.cname like 'rdbms' and c.cid=e.cid);

可替换地:

select sid 
from enroll e, 
     course c 
where cname like 'java' and c.cid=e.cid
union 
select sid 
from enroll e, 
     course c 
where cname like 'rdbms' and c.cid=e.cid;

第二种选择:

select sid 
from enroll 
where cid in (select cid 
              from course 
              where cname like 'java' 
                 or cname like 'rdbms');

上述所有问题都能让我得到预期的结果。

要查找已经使用java rdbms的学生的sids,我只修改了所有3个但下面的第1和第3个查询不起作用。

select sid 
from enroll e, 
     course c 
where (c.cname like 'java' and c.cid=e.cid) 
  and (c.cname like 'rdbms' and c.cid=e.cid);

替代:

select sid 
from enroll e, 
     course c 
where cname like 'java' and c.cid=e.cid
intersect 
select sid 
from enroll e, 
     course c 
where cname like 'rdbms' and c.cid=e.cid;

第二种选择:

select sid 
from enroll 
where cid in (select cid 
              from course 
              where cname like 'java' and cname like 'rdbms');

4 个答案:

答案 0 :(得分:1)

编写OR查询的一种方法是:

SELECT DISTINCT sid
  FROM enroll e JOIN course c ON c.cid = e.cid
 WHERE c.cname IN ('java', 'rdbms');

编写AND查询的一种方法是:

SELECT DISTINCT sid
  FROM enroll e JOIN course c ON c.cid = e.cid
 WHERE c.cname IN ('java', 'rdbms')
 GROUP BY sid
HAVING COUNT(*) = 2;

这要求所选学生的注册表中出现两行,每门课程一行(假设学生不能为一门课程注册两次)。如果他们可以,那么你需要在HAVING子句中使用类似COUNT(DISTINCT cid) = 2的东西。


分析您的非工作查询:

select sid 
from enroll e, 
     course c 
where (c.cname like 'java' and c.cid=e.cid) 
  and (c.cname like 'rdbms' and c.cid=e.cid);

这可以写得更清楚,也许是:

SELECT sid 
  FROM enroll e JOIN course c ON c.cid = e.cid
 WHERE (c.cname = 'java' AND c.cname = 'rdbms');

现在,如果一个课程名称是'java',它显然不是'rdbms',反之亦然,所以没有一行可以满足条件。您必须使用相同的sid分析两行。因此,这个查询不够复杂,无法回答这个问题。

第二种选择:

select sid 
from enroll 
where cid in (select cid 
              from course 
              where cname like 'java' and cname like 'rdbms');

这遇到了同样的问题;在Course表中不能有一行,其中cname同时是'java'和'rdbms'。

答案 1 :(得分:0)

我建议您提供的信息比“不工作”更多。你应该描述一下你期待什么以及你得到了什么。

话虽如此,我可以建议一个查询来替换第一个,这样可以获得同时兼顾java和rdbms的信息:

select distinct sid 
from enroll e, course c 
where c.cid=e.cid
and c.cname in ('java','rdbms');

有许多不同的方法可以做到这一点,根据您的最终要求,可能有更好的方法。毫无疑问,有人会提出一种“更好”的方式,但这实际上取决于最终要求。

您的上一个查询不起作用,因为它的这一部分:

select cid from course where cname like 'java' and cname like 'rdbms'

给我一个课程记录,课程名称是java,课程名称是rdbms

当然没有这样的记录。这就像是把我介绍给一个名叫弗雷德的人,他的名字叫鲍勃。

同样取决于RDBMS,使用没有通配符的方式也不会给你带来任何结果。

答案 2 :(得分:0)

试试这个

select sid 
from enroll e
where exists(select 0
              from course c
              where c.cname like 'java'
                and c.cid = e.cid)
  and exists(select 0
              from course c
              where c.cname like 'rdbms'
                and c.cid = e.cid)
祝你好运

答案 3 :(得分:0)

第一个和第三个不工作的原因是他们声明cname应该同时是'java'和'rdbms'!第三个查询可以像这样重写:

select distinct sid 
  from enroll 
  where cid in (select cid 
                  from course 
                where cname like 'java' or cname like 'rdbms');

这应该会为学生提供所有已经使用java或rdbms cources的记录。