这几天数据库上机,关于全称量词的某道题想了很久才明白一些,写下这篇博客做下巩固。

说明

SQL中没有全程量词,但是可以将其转化为等价的带有存在量词的语句,即可以用exists 代替全称量词。

转化公式

数学描述

$(\forall x)P=\neg (\exists x(\neg P) )$

自然语言描述

对于所有$x$ ,$P$ 成立 等价于 存在$x$ 使$P$ 不成立的情况不存在。

举个栗子

上面的没看懂没关系,来看一个教科书上的例子。

查询至少选修了学号为03051066选修的全部课程的学生学号。

数学语言描述

  • $x$ 表示学号为$03051066$ 选修了课程$cno$
  • $P$ 表示学生$sno$ 也选修了课程$cno $

则有,$(\forall x)P=\neg (\exists x(\neg P) )$ 。

自然语言描述

有上述数学描述可得,存在学号为$03051066$ 选修了课程$cno$ 而学生$sno$ 没有选修课程$cno $ 的情况不存在。

换句话来说,也就是:

从$sc$ 中筛选出的每个学号$Number$,不存在这样的课程

  • 学号为$03051066$ 的选修过
  • 学号为$Number$ 的人未选修

C/C++语言描述

set<sno>select;
for(int i=0;i<sc.size();++i){
    bool flag=1;
    for(int j=0;j<sc.size();++j){
        if(sc[j].sno=='03051066'){
            bool galf=1;
            for(int k=0;k<sc.size();++k){
                if(sc[i].sno==sc[k].sno&&sc[j].cno==sc[k].cno){
                    galf=0;
                    break;
                }
            }
            if(galf){
                flag=0;
                break;
            }
        }
    }
    select.insert(sc[i].sno);
}

Python语言描述

def exists_3(Number, course):
  for z in sc:
    if z.sno == Number and z.cno == course:
      return False
  return True

def exists_2(Number):
  for y in sc:
    if y.sno == '03051066' and exists_3(Number, y.course) == True:
 	  return False
  return True

select = set()
for x in sc:
  if exists_2(x.sno) == False:
    select.add(x.sno)

SQL语言描述

select sno,sname
from student
where sno in (
  select sno
  from sc scx
  where not exists(
    select *
	from sc scy
    where scy.sno='03051066' and not exists(
      select *
      from sc scz
   	  where scz.sno=scx.sno and scz.cno=scy.cno
    )
  )
);