嵌套查询
在SQL语音中,一个select-from-where语句称为一个查询块。将一个查询块嵌套在另一个查询块的where子句或HAVING短语的条件中的查询称为嵌套查询。在嵌套查询中上层的查询块称为外层查询或父查询,下层的查询块称为内层查询或子查询。
带有IN谓词的子查询
先分步来进行查询
然后将第一步查询嵌套在第二步查询的条件中,构造嵌套查询。
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(select Sdept
FROM Student
WHERE Sname='刘晨');
该查询也可通过自身连接来完成:
select S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨';
由此可知实现同一个查询有多种方法,只是不同方法的效率不同。
涉及三个属性的查询
SELECT Sno,Sname
FROM Student
WHERE Sno IN
(select Sno
FROM SC
WHERE Cno IN
(SELECT Cno
FROM Course
WHERE Cname='信息系统'
)
);
上诉两个例子中子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询,与之相反的子查询称为相关子查询,整个查询语句称为相关嵌套查询。
带有比较运算符的子查询
带有比较运算符的子查询是指父查询于子查询之间用比较运算符进行连接,当能知道内层查询返回的是单个值时,可以用>、<、=、>=、<=、!=或<>等比较运算符。
找出学生超过自己选修课平均成绩的课程号
select Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
带有ANY(SOME)或ALL谓词的子查询
子查询返回单值时可以用比较运算符,但返回多值时要用ANY(有的系统用SOME)或ALL谓词修饰符。而使用ANY或ALL谓词时则必须同时使用比较运算符。语义如下:
ANY 大于子查询结果中的某个值
ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
= ANY 大于等于子查询结果中的某个值
= ALL 大于等于子查询结果中的所有值
<= ANY 小于等于子查询结果中的某个值
<= ALL 小于等于子查询结果中的所有值
= ANY 等于子查询结果中的某个值
= ALL 等于子查询结果中的所有值(通常没有实际意义)
!=(或<>) ANY 不等于子查询结果中的某个值
!=(或<>) ALL 不等于子查询结果中的任何一个值
查询非计算机系中比计算机系任意学生年龄小的学生姓名和年龄
select Sname,Sage
FROM Student
WHERE Sage<ANY(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS'; /*此为父查询块中的条*/
查询非计算机系中比计算机系所有学生年龄都小的学生姓名及年龄
select Sname,Sage
FROM Student
WHERE Sage<ALL
(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS'; /*此为父查询块中的条*/
该查询也可以用聚焦函数实现:
select Sname,Sage
FROM Student
WHERE Sage<
(SELECT MIN(Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS'; /*此为父查询块中的条*/
用聚集函数实现子查询通常比直接用ANY或ALL查询效率要高。
下面是ANY、ALL与聚集函数的对应关系:
= | <>或!= | < | <= | > | >= | |
---|---|---|---|---|---|---|
ANY | IN | – | <MAX | <=MAX | >MAX | >=MAX |
ALL | – | NOT IN | <MIN | <=MIN | >MIN | >=MIN |
带有EXISTS谓词的子查询
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
查询所有选修了1号课程的学生姓名:
select Sname,Sage
FROM Student
WHERE EXISTS
(SELECT*
FROM SC
WHERE Sno=Student.Sno AND Cno='1');
查询选修了全部课程的学生姓名
SQL中没有全称量词(for all),但是可以把带有全称量词的谓词转换为等价的带有存在量词的谓词。
select Sname
FROM Student
WHERE NOT EXISTS
(SELECT*
FROM Course
WHERE NOT EXISTS
(SELECT*
FROM SC
WHERE Sno=Student.Sno
AND Cno=Course.Cno));
插入的数据中无满足条件的,所有查询结果无
查询至少选修了学生201215122选修的全部课程的学生号码
select DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT*
FROM SC SCY
WHERE SCY.Sno='201215122' AND
NOT EXISTS
(SELECT*
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND
SCZ.Cno=SCY.Cno));
本次实验到此结束