码迷,mamicode.com
首页 > 其他好文 > 详细

检索所有课程都选修的的学生的学号与姓名

时间:2014-12-18 20:26:25      阅读:450      评论:0      收藏:0      [点我收藏+]

标签:style   http   ar   color   使用   sp   for   on   数据   

  这是SHU数据库原理上机题目中的一道。全部题目:http://www.docin.com/p-739281393.html

  代码网上有:

  select xh,xm

  from s

  where not exists

  (select * from c 

  where  not exists

  (select * from e

  where xh=s.xh and kh=c.kh

  )

  ) 

  其中s是学生表,c是课程表,e是选课表

  上课没注意听,实验验收前看了很久没看懂。网上的讲解没看明白,并且还有错的讲解(该页的最后会有)。直接跟老师说这个不懂,老师让我中午去找他。花了20多分钟,我懂了。老师说上课还是要听,我深以为然。

  这代码有三种方式去理解:

  1、离散数学中的谓词逻辑演算系统

  先来复习一下

  ∃x∀yR(xy) :存在x对于任意的y满足关系R(xy)。

  ﹁∀yW(y):不是所有的y都满足关系W(y),那么就是存在y不满足关系R,即∃y﹁W(y)

  令f(x):x是学生;g(y):y是课程;r(xy):学生x选修了课程y。

  “所有课程都选修的学生”可以表示为∃x∈f(x)∧∀y∈g(y)∧r(xy) ,就是存在学生任意一门课都选了。

  SQL语言中没有全称量词,所以通过双重否定来实现

  ﹁﹁((∃x∈f(x)∧∀y∈g(y))∧r(xy)) => ∃x∈f(x)∧﹁(∃y∈g(y)∧﹁r(xy))

  对于﹁∀yR(xy),理解为不是所有的y都满足关系R,那么就是存在y不满足关系R,∃y﹁R(xy)

  然后用这个式子与上面的代码对照。  

  ﹁就相当于一个not exists,其实相当于是select

  select xh,xm from s  等价于∃x∈f(x)

  select * from c 等价于 ∃y∈g(y)

  where  not exists(select * from ewhere xh=s.xh and kh=c.kh) 等价于 ﹁r(xy) 

 

  

  2、用C++的编程思想来理解

  for(int i=0;i<s.length;i++)

  {

    for(int j=0;j<c.length;j++)

    {

      if(学生i没有选修j课程) break;

    }

    if(j==c.length) i就是选修了所有课程的学生;

  }

  两个not exists可以这样解释,依次从学生表里找一个学生,让这个学生去选课表里找课程。如果遍历到某课程该学生没有选修,就结束,然后开始遍历下一个学生。如果是遍历完课表的话,就代表着该学生学修了所有的课程。

  也就是说我们不去用语言来翻译代码,换种思维来理解它。

 

  3、纯粹记忆

  如果查询“全部”内容,需用到全称量词,但SQL语言只提供存在量词,我们用存在量词双重否定来解决

  SELECT <查询内容> FROM 表1 WHERE

    NOT EXISTS(SELECT * FROM 表2 WHERE

    NOT EXISTS(SELEST * FROM 表3 WHERE

               表3与表1联接条件 AND 表3与表2联接条件))

  表1是查询结果所需要的表

  表2是全部内容所在的表

  表3是将联接上述两表的表

 例:1.查询使用了全部零件的工程名称(理解为没有零件是不用的)

    2.查询至少用了供应商S1所供应的的全部零件的工程号

  这种方法是不去理解no exists的原理,记住格式就好了。应付考试专用。

 

  关于上面提到的错误的讲解:

  有人说代码可以这样写:

  select xh,xm
  from s
  where xh in
  (
  select xh from e group by xh
  having count(*) = (select count(*) from c)
  )

  这样理解的,统计课程的数量,记为n,假如某学生所修的课程的数量为n。那么该学生就是选修所有课程的人。

  刚开始我也以为这样可以的。因为逻辑上是正确的。

  我在课程表c中添加了几组数据,使得有人选修了所有课号的课。但是运行最上面的代码(代码1)和这条代码(代码2)的运行结果是不同。

  那么导致结果不同的原因是什么呢?课程表c里有重修课程,也就是有课程虽然是相同的课程号,但是由于开课的时间不同,所以它们不算一门课。

  那么上面的代码有可取的地方么?有,特殊的情况是可以用的,就是事件是唯一的的时候。

  

  

检索所有课程都选修的的学生的学号与姓名

标签:style   http   ar   color   使用   sp   for   on   数据   

原文地址:http://www.cnblogs.com/Potato-lover/p/4172461.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!