现实中,很多情况下需要进行下述条件判断
子查询是出现在WHERE子句中的SELECT语句被称为子查询,子查询返回了一个集合。
基本语法:查询语句 [NOT] IN 子查询
语义:查询语句产生的结果是否在子查询当中
SELECT sn, sname FROM student WHERE sn IN (SELECT sn FROM sc WHERE cn="001");
括号中产生的结果是一个集合(这里称为子集合),集合中的元素是学过001课程的学生的学号。前半部分的查询语句是从student中每取一条记录来查看记录中的sn是否在子集合中。如果是则将该记录进行标记,否则取出下一条继续比较。最后将被标记的记录中sn和snames属性值输出。
SELECT sn FROM sc WHERE cn="001" AND sn IN (SELECT sn FROM sc WHERE cn="002");
查询分为外层查询和内层查询
外层查询的参数可以被带入到内层查询中,而内层查询的参数不能在外层查询中使用,这和高级编程中的循环一个道理。
当内层查询没有使用到外查询的参数时,我们可以内层查询是非相关子查询。上图中就是非相关子查询。判断是否相关最简单的方式就是内层查询是否能独立执行。
上图的例子中内层子查询使用到了外层的变量(Stud),这样内层查询就不能独立执行
基本语法:查询语句 Θ SOME 子查询
查询语句 Θ ALL 子查询
Θ 是运算符:<,>,<=,>=,<>
Θ SOME表示前面的记录需要与子查询结果中某个记录做运算,如果为TRUE则该记录被接受
Θ ALL表示前面的记录需要与子查询结果中所有记录做运算,如果全为TRUE则该记录才被接受
SELECT tname FROM teacher WHERE salary <= ALL( SELECT salary FROM teacher)
SELECT sn FROM sc WHERE cn="001" AND score < SOME( SELECT score FROM sc WHERE cn = "001")
SELECT sname FROM student WHERE 60 > ALL( SELECT score FROM sc WHERE sc.sn = student.sn)
SELECT cn FROM sc,student WHERE sname="张三" AND sc.sn=student.sn AND score <=ALL( SELECT score FROM sc WHERE sn=student.sn)
基本语法: [NOT] EXISTS (子查询)
含义:判断子查询结果集是否为空,当子查询为空时,EXISTS判断为false,而NOT EXISTS判断为true。NOT EXISTS使用情况比较多
等价转换为不存在这样一门课程,该课程由001教师主讲并且该课程该同学没学过
SELECT sname FROM student WHERE NOT EXISTS( SELECT * FROM course WHERE tn="001" AND NOT EXISTS( SELECT * FROM sc WHERE sn=student.sn AND cn=course.cn) )
等价于不存在这样的学生,他学过李明老师的课
SELECT sname FROM student WHERE NOT EXISTS( SELECT * FROM course,sc,teacher WHERE course.cn=sc.cn AND teacher.tn=course.tn AND tname="李明" AND student.sn=sc.sn)
等价于不存在98030101同学学过的课程,该同学没有学过
SELECT sn FROM sc AS sc1 WHERE sn !="98030101" AND NOT EXISTS( SELECT * FROM sc AS sc2 WHERE sn="98030101" NOT EXISTS( SELECT * FROM sc AS sc3 WHERE sc2.cn=cn AND sn=sc1.sn) )
结果计算和聚类计算是对查询结果集中的一些数据进行计算
SELECT t1.tname AS teacher1, t2.tname AS teacher2,t1.salary-t2.salary FROM teacher AS t1, teacher AS t2 WHERE t1.salary >t2.salary
聚类计算
SELECT SUM(salary) FROM teacher
SELECT AVG(score) FROM sc,course WHERE sc.cn=course.cn AND course.cname="数据库"