USE my_test;
CREATE TABLE `student` (
`Sno` VARCHAR(32) NOT NULL,
`Sname` VARCHAR(20) DEFAULT NULL,
`Ssex` VARCHAR(1) DEFAULT NULL,
`Sage` SMALLINT(1) DEFAULT NULL,
`Sdept` VARCHAR(32) DEFAULT NULL,
PRIMARY KEY (`Sno`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `my_test`.`student` (`Sno`, `Sname`, `Ssex`, `Sage`, `Sdept`) VALUES ('200215121', '李勇', '男', '20', 'CS');
INSERT INTO `my_test`.`student` (`Sno`, `Sname`, `Ssex`, `Sage`, `Sdept`) VALUES ('200215122', '刘晨', '女', '19', 'CS');
INSERT INTO `my_test`.`student` (`Sno`, `Sname`, `Ssex`, `Sage`, `Sdept`) VALUES ('200215123', '王敏', '女', '18', 'MA');
INSERT INTO `my_test`.`student` (`Sno`, `Sname`, `Ssex`, `Sage`, `Sdept`) VALUES ('200215124', '张立', '男', '19', 'IS');
CREATE TABLE `Course` (
`Cno` VARCHAR(32) NOT NULL,
`Cname` VARCHAR(20) DEFAULT NULL,
`Cpno` VARCHAR(32) NOT NULL,
`Ccredit` INT DEFAULT NULL,
PRIMARY KEY (`Cno`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('1', '数据库', '5', '4');
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('2', '数学', '', '2');
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('3', '信息系统', '1', '4');
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('4', '操作系统', '6', '3');
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('5', '数据结构', '7', '4');
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('6', '数据处理', '', '2');
INSERT INTO `my_test`.`course` (`Cno`, `Cname`, `Cpno`, `Ccredit`) VALUES ('7', 'PASCAL语言', '6', '4');
CREATE TABLE `SC` (
`Sno` VARCHAR(32) NOT NULL,
`Cno` VARCHAR(32) NOT NULL,
`Credit` INT DEFAULT NULL,
PRIMARY KEY (`Sno`,`Cno`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `my_test`.`sc` (`Sno`, `Cno`, `Credit`) VALUES ('200215121', '1', '92');
INSERT INTO `my_test`.`sc` (`Sno`, `Cno`, `Credit`) VALUES ('200215121', '2', '95');
INSERT INTO `my_test`.`sc` (`Sno`, `Cno`, `Credit`) VALUES ('200215121', '3', '88');
INSERT INTO `my_test`.`sc` (`Sno`, `Cno`, `Credit`) VALUES ('200215122', '2', '90');
INSERT INTO `my_test`.`sc` (`Sno`, `Cno`, `Credit`) VALUES ('200215122', '3', '80');
例1:查询所有选修了1号课程的学生的姓名。
解法1:利用exists
首先取Student表中的一个元组,然后在SC表中依次找SC.Sno=该元组的Sno,并且对应的Cno='1',
如果存在,则外层查询的where子句返回为真,则Student表中的该元组可以输出。
然后依次遍历Student表中的其他元组。
举个例子:对于在学生表中学号等于2002151121这个元组,
在SC表中第一条记录即符合条件,然后where 子句返回 true,所以该条元组可以输出。然后依次遍历。
SELECT Sname
FROM Student
WHERE EXISTS
(
SELECT *
FROM SC
WHERE SC.cno='1' AND Student.Sno=sc.Sno
);
解法2:利用连接查询
SELECT Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND SC.Cno='1';
例2:查询没有选修1号课程的学生的姓名。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(
SELECT *
FROM SC
WHERE SC.cno='1' AND Student.Sno=sc.Sno
);
例3:查询选修了全部课程的学生姓名。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(
SELECT *
FROM Course
WHERE NOT EXISTS
(
SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno=Course.Cno
)
);
查找语义:查询这样的学生,没有一门课程是他不选修的。
查找过程:
首先,选取Student表中的一个元组,然后在依次判断Course表中的每个元组是否可以输出,
只要有一个课程可以输出,则最外层查询的where子句返回为false;
而在判断某个课程是否可以输出时,则要利用第三层查询,利用当前的学号和当前的课程号,
在SC表中查询,如果存在,则第二层查询where子句返回false。至此,每一门课程都不可以输出时,
这个学号对应的元组才可以输出。表示这个学生选修了全部的课程。
例4:至少选修了学生200215122选修的全部课程的学生号码。
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
(
SELECT *
FROM SC SCY
WHERE SCY.Sno='2002151122' AND
NOT EXISTS
(
SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND SCZ.Cno=SCY.Cno
)
);
查询语义:不存在这样的课程y,学生200215122选修了y,而学生x没选。
查询过程:先在SCX表中选一条记录,比方说第一条,然后再看SCY表中,
只有SCY表中全部不能输出,第一层查询的where子句才返回true,
第一条记录就可以输出;所以就要一次查看SCY表中的每一个元组,
前三个,因为学号首先不满足=200215122所以必然不能输出,
第四个的话,就要看其AND后面的not exists返回什么值,
而这又取决于第三层查询中是否存在满足学号等于SCX.Sno且课程号=SCY.Cno的元组,
经查看,有 ,则返回false,所以第四个也不能输出,第五个类似,
所以,第一层查询的not exists返回true。所以第一条记录可以输出。