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


      这是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里有重修课程,也就是有课程虽然是相同的课程号,但是由于开课的时间不同,所以它们不算一门课。

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

      

      

  • 相关阅读:
    验证视图状态 MAC 失败的处理办法总结![come from internet]
    在ie6上 让他显示png图片
    挑灯夜战 css hack 再次学习 IE浏览器常见的9个css Bug以及解决办法
    fileupload上传 and IE8 and VS2008 实现图片预览[new Name:经典的Fakepath错误]
    大项目开发语言的选择
    虚拟机安装linux:未找到任何驱动程序
    objectc中的bool
    关于数字内容网站的一些想法
    iphone开发论坛
    在centos5.3下安装mysql5启动时报错
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/4172461.html
Copyright © 2020-2023  润新知