学校的部分关系模式如下:
学生(学号,姓名,年龄,学院名,专业)
课程(课程号,课程名,学时,学分)
选修(课程号,学号,成绩)
检索选读所有课程的学生姓名
郭春柱书上给的答案是这样的:
SELECT 学生.姓名
FROM 学生
WHERE NOT EXISTS
(SELECT *
FROM 课程
 WHERE NOT EXISTS
 (SELECT *
  FROM 选修
  WHERE 学生.学号=选修.学号 AND 选修.课程号=课程.课程号书是填空题,加粗的部分是要填入的答案,和我另一个提问的问题感觉差不多,但我就是不明白为什么这样就能查出来,加粗的部分是什么意思,逻辑是什么,谢谢啦。我提问的另一个问题:http://topic.csdn.net/u/20120313/19/9b66fb35-5d1c-4639-9310-744317f4301f.html

解决方案 »

  1.   

    --不存在 这样的产品 01 买过了,x没买过SELECT 客户号
    FROM 客户产品 客户产品1
    WHERE NOT EXISTS
    (
    -- 01 买过的产品 但是客户 x 没买过
    SELECT *
     FROM 客户产品 客户产品2
     WHERE 客户号='01' AND NOT EXISTS
    (
     -- 客户1买过的产品,客户未知也买过(不存在01买过的,未知客户没买过的)
    SELECT *
     FROM 客户产品 客户产品3
     WHERE 客户产品1.客户号=客户产品3.客户号 
     AND 客户产品2.产品号=客户产品3.产品号
     
     我要找 至少买了 01 买过的产品 第一个select
    所以我先要知道01 买了那些产品  第二个select
    这个客户买的产品和 01 买的产品 对比 第三个select
      

  2.   

    所有的X均满足条件p,等价于不存在X不满足P,因为SQL语言不存在全称量词,所以只好使用两个NOT EXISTS来表达。第一个NOT EXISTS 的子查询选取学生没有参加的课程,如果为空则说明该学生参加了所有的课程,第二个同理,为空则取,不为空则放弃。
      

  3.   

    这个答案显得有些复杂,而且用了两次not exists,效率会很差的.
    看看这个思路,对"选修课"按学号分组,如果一个学生选修了所有的课程,那分组后他的Count(*)必然要等于所有课程的数select 姓名 from 学生 a,
    (select 学号 from 选修
    group by 学号 having COUNT(*)=(select COUNT(*) from 课程))b
    where a.学号=b.学号
      

  4.   

    用两个not exists来表示全部满足的条件确实比较抽象.可以这么去考虑问题:
    选修全部课程的学生+选修部分课程的学生+没有任何选修课程的学生=全部学生
    那么选修全部课程的学生只需要在学生集合中排除掉只选修部分课程或是没有任何选修课程的学生即可.问题的关键就在于如何能找到哪些是只选修部分课程或是没有任何选修课程的学生.
    而实际上这些部分选修的或是根本没有选修课程的学生,他们都一个共性,就是说存在着不能完全满足
    学生.学号=选修.学号 AND 选修.课程号=课程.课程号的情况.
    如果用sql书写就会形成下面的语句:SELECT 学生.姓名
    FROM 学生
    WHERE EXISTS
    (SELECT *
    FROM 课程
     WHERE NOT EXISTS
     (SELECT *
      FROM 选修
      WHERE 学生.学号=选修.学号 AND 选修.课程号=课程.课程号这条SQL语句查询到的结果就是只选修了部分课程的或是什么课程都没选修的学生,因为他们存在着不能完全满足内联条件的情况.所以在学生集合在再一次用到 not exists语句把上一次查询到的结构排除掉就会得到选修全部课程的学生SELECT 学生.姓名
    FROM 学生
    WHERE NOT EXISTS
    (SELECT *
    FROM 课程
     WHERE NOT EXISTS
     (SELECT *
      FROM 选修
      WHERE 学生.学号=选修.学号 AND 选修.课程号=课程.课程号
      

  5.   

    上面的两条sql语句最后还缺两个")",补上才是正确的语句.
    如何能理解不能完全满足内联条件的情况?
    举个例子来说,学生表和课程表,学生表中有3个记录,课程表中有4个记录,如果学生表中的每一个都选修了全部课程,那么内联后就会是
    学生-课程
    1-1
    1-2
    1-3
    1-4
    2-1
    2-2
    2-3
    2-4
    3-1
    3-2
    3-3
    3-4   
    在这种情况下, not exists(select * from 选修 where 学生.id=选修.学生id and 选修.课程id=课程.id)就会返回一个空的结果.因为不存在不满足完全内联条件的情况.
    如果把最后两行记录3-3,3-4去掉,那么上面的语句查询的结果就是学生3,因为他存在着不能完全满足内联的要求.
    exists和in的用法是相似的,只要有一个条件满足就会成立,所以如果要查询必须满足全部条件的就必须把所有不满足条件的全部排除才能得到正确的结果.
      

  6.   

    用一句话来描述解决方案:是否有不符合学生.学号=选修.学号 AND 选修.课程号=课程.课程号的情况(即没全部选修),如果有的话排除它.