SQL练习4-SELECT(连接查询、嵌套查询)

连接查询
连接查询的WHERE子句中来连接两个表的条件称为连接条件或连接谓词,其一般格式:
[<表名 1>.]<列名 1><比较运算符>[<表名 2>.]<列名 2>
其中比较运算符主要为=、>、<、>=、<=、!=(或者是<>)等。
此外连接谓词还可以使用以下形式:
[<表名 1>.]<列名 1> BETWEEN [<表名2>.]<列名 2> AND [<表名 2>.]<列名 3>
当连接运算符为=时,称为等值连接。使用其他运算符称为非等值连接。
【例3.49】查询每个学生及其选修课程的情况

SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno

在这里插入图片描述
【例3.50】对例3.49用自然连接完成

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno=SC.Sno

在这里插入图片描述
【例3.51】查询选修2号课程且成绩在80分以上的所有学生的学号和姓名

SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND
	SC.Cno='2' AND SC.Grade>80

在这里插入图片描述
从SC中挑选出Cno='2’并且Grade>80的元组形成一个中间关系,再和Student中满足连接条件的元组进行得到最终的结果关系
自身连接
一个表与其自己进行连接称为表的自身连接,在进行自身连接的时候,需要对表取别名。
【例3.52】查询每一门课的间接先修课(即先修课的先修课)

SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno=SECOND.Cno

在这里插入图片描述
在这里插入图片描述
外连接
【例3.53】以Student表为主体列出每个学生的基本情况及其选课情况,若学生没有选课,仍把Student的悬浮元组保存在结果关系中。

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON(Student.Sno=SC.Sno)

在这里插入图片描述
本例为左外连接,列出的是左边关系

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student RIGHT OUTER JOIN SC ON(Student.Sno=SC.Sno)

在这里插入图片描述
上例是右外连接,列出右边关系中的所有元组
多表连接
连接操作除了可以是两表连接、一个表与其自身连接外,还可以是两个以上的表进行的连接,后者通常称为多表连接
【例3.54】查询每一个学生的学号、姓名、选修的课程名及成绩

SELECT Student.Sno,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno

在这里插入图片描述
关系数据库管理系统在执行多表连接的时候,通常是先进行两个表的连接操作,再将其连接的结果与第三个表进行连接。
嵌套查询
一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套再另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。上层的查询块称为外层查询或父查询,下层查询块称为内层查询或子查询。
【例3.55】查询与“刘晨”在同一个系学习的学生
解法一:

/*确定“刘晨”所在的系名*/
SELECT Sdept
FROM Student
WHERE Sname='刘晨'
/*结果为CS*/
/*查找所有子啊CS系学习的学生*/
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept='CS'

在这里插入图片描述
解法二:

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
	(SELECT Sdept
	FROM Student
	WHERE Sname='刘晨'
	)

上例子查询的查询条件不依赖父查询,称为不相关子查询。其求解的方法是由里向外处理,即先执行子查询,子查询的结果用于建立父查询的查找条件。

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept =
	(SELECT Sdept
	FROM Student
	WHERE Sname='刘晨'
	)

当用户确定内层查询返回是单个值时,可以用比较运算符。上例中可以用=代替IN
解法三:
用自身连接来完成

SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨'

【例3.56】查询选修了课程名为“信息系统”的学生学号和姓名
解法一:

SELECT Sno,Sname
FROM Student
WHERE Sno IN
	(SELECT Sno
	FROM SC
	WHERE Cno IN
		(SELECT Cno
		FROM Course
		WHERE Cname='信息系统'
		)
	)

在这里插入图片描述
该查询从里向外,先在Course关系中找到“信息系统”的课程,结果为3,然后再SC关系中找到选修了3号课程的学生学号。最后再Student关系中取出Sno和Sname
解法二:连接查询实现

SELECT Student.Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND
	  SC.Cno=Course.Cno AND
	  Course.Cname='信息系统'

【例3.57】找出每个学生超过他自己选修课程平均成绩的课程号

SELECT Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
			  FROM SC y
			  WHERE y.Sno=x.Sno)

在这里插入图片描述
x是表SC的别名,又称为元组变量,可以用来表示SC的一个元组。上例中子查询的值与父查询是相关的,所以该查询是相关子查询。
上例分为三个步骤:从外层查询中取出SC的一个元组x,将元组的Sno值传递给内层查询;执行内层查询得到某个值,再用这个值得到外层查询;执行外层查询,得到结果。
带有ANY(SOME)或者ALL谓词的子查询
在这里插入图片描述
【例3.58】查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生的姓名和年龄
解法一:

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<(SELECT MAX(Sage)
			FROM Student
			WHERE Sdept='CS')
AND Sdept<>'CS'

【例3.59】查询非计算机科学系中比计算机科学系所在学生年龄都小的学生的姓名和年龄
解法一:

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与聚集函数的对于关系如下图所示:
在这里插入图片描述

发布了61 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44652687/article/details/104893953