SQL练习5-SELECT(嵌套查询、EXISTS、集合查询、基于派生表的查询、SELECT总结)

SELECT:

带有EXISTS谓词的子查询:
EXISTS代表存在量词 \exists 。带有EXISTS谓词的子查询不反回任何数据,只产生逻辑真值“true”或者逻辑假值“false”

【例3.60】查询所有选修了1号课程的学生姓名

SELECT Sname
FROM Student
WHERE EXISTS
	(SELECT *
	FROM SC
	WHERE Sno=Student.Sno AND Cno='1')

在这里插入图片描述
使用存在量词EXISTS后,若内层查询结果为非空,那么外层的WHERE子句返回真值,否则返回假值。
与EXISTS谓词对应的是NOT EXISTS谓词。使用存在量词NOT EXISTS后,若内层查询结果为空,则外层的WHERE子句返回真值,负责返回假值。
【例3.61】查询没有选修1号课程的学生姓名

SELECT Sname
FROM Student
WHERE NOT EXISTS
	(SELECT *
	FROM SC
	WHERE Sno=Student.Sno AND Cno='1')

在这里插入图片描述
【例3.62】查询选修了全部课程的学生姓名
SQL中没有全称量词 \forall ,但是可以把带有全称量词的谓词转化为等价的带有存在量词的谓词:
( x ) P ¬ ( x ( ¬ P ) ) (\forall x)P \equiv \neg (\exists x(\neg P))
由于没有全称量词,可将题目的意思转化为等价的用存在量词的形式;查询这样的学生,没有一门课程是他不选修的。

SELECT Sname
FROM Student
WHERE NOT EXISTS
	(SELECT *
	FROM Course
	WHERE NOT EXISTS
			(SELECT *
			FROM SC
			WHERE Sno=Student.Sno
			AND Cno=Course.Cno))

在这里插入图片描述

【例3.63】查询至少选修了学生201215121选修的全部课程的学生号码
表达的语义为不存在这样的课程y,学生201215121选修了y,而学生x没有选。

SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
	(SELECT *
	FROM SC SCY
	WHERE SCY.Sno='201215121' AND
			NOT EXISTS
			(SELECT *
			FROM SC SCA
			WHERE SCA.Sno=SCX.Sno AND
				  SCA.Cno=SCY.Cno))

在这里插入图片描述
集合查询:
SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作。集合操作主要包括并操作UNION、交操作INTERSECT和差操作EXCEPT。注意:参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同。
【例3.64】查询计算机科学系的学生及年龄不大于19岁的学生
即查询计算机科学系的所有学生与年龄不大于19岁学生的并集。

FROM Student
WHERE Sdept='CS'
UNION
SELECT *
FROM Student
WHERE Sage<='19'

在这里插入图片描述
使用UNION将多个查询结果合并起来时,系统会自动去掉重复的元组,如果要保留重复元组则用UNION ALL操作符

SELECT *
FROM Student
WHERE Sdept='CS'
UNION ALL
SELECT *
FROM Student
WHERE Sage<='19'

在这里插入图片描述
【例3.65】擦好像选修了课程1或者是课程2的学生
即选修课程1的学生与选修课程2的学生集合的并集

SELECT Sno
FROM SC
WHERE Cno='1'
UNION 
SELECT Sno
FROM SC
WHERE Cno='2'

在这里插入图片描述
【例3.66】查询计算机科学系的学生与年龄不大于19岁的学生的交集
解法一:

SELECT *
FROM Student
WHERE Sdept='CS'
INTERSECT
SELECT *
FROM Student
WHERE Sage<=19

在这里插入图片描述
解法二:
用AND来实现

SELECT *
FROM Student
WHERE Sdept='CS' AND Sage<=19

【例3.67】查询既选修了课程1又选修了课程2的学生。
解法一:

SELECT Sno
FROM SC
WHERE Cno='1'
INTERSECT
SELECT Sno
FROM SC
WHERE Cno='2'

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

SELECT Sno
FROM SC
WHERE Cno='1' AND Sno IN
					(SELECT  Sno
					FROM SC
					WHERE Cno='2')

【例3.68】查询计算机科学系的学生与年龄不大于19岁的学生的差集
解法一:

SELECT *
FROM Student
WHERE Sdept='CS'
EXCEPT
SELECT *
FROM Student
WHERE Sage<=19

解法二:

SELECT *
FROM Student
WHERE Sdept='CS' AND Sage>19

在这里插入图片描述

EXISTS的使用总结:

1.EXISTS代表量词 \exists ,带有EXISTS的谓词的子查询只返回“true”或者“false”
2.使用存在量词EXISTS后,若内层查询结果为非空,则外层的WHERE子句返回真值,否则返回假值
3.EXISTS 与NOT EXISTS 相对应。使用存在量词NOT EXISTS后,若内层查询结果为空,则外层的WHERE子句返回真值,否则返回假值。

基于派生表的查询:改写【例3.57】、【例3.60】,及两种方法的对比:

子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表称为主查询的查询对象。
【例3.57】找出每个学生超过他自己的选修课程平均成绩的课程号

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

在这里插入图片描述
改写【例3.57】

SELECT Sno,Cno
FROM SC,(SELECT Sno,Avg(Grade)FROM SC GROUP BY Sno)
		AS Avg_sc(avg_sno,avg_grade)
WHERE SC.Sno=Avg_sc.avg_sno and SC.Grade>=Avg_sc.avg_grade

【例3.60】查询所有选修了1号课程的学生姓名

SELECT Sname
FROM Student
WHERE EXISTS
	(SELECT *
	FROM SC
	WHERE Sno=Student.Sno AND Cno='1')

在这里插入图片描述
改写【例3.60】

SELECT Sname
FROM Student,(SELECT Sno FROM SC WHERE Cno='1')AS SCI
WHERE Student.Sno=SCI.Sno

对比:
1.原方法的子查询是出现在WHEyuanRE子句中的,基于派生表的查询时出现在FROM子句中的。
2.原方法是WHERE子句找到满足条件的元组基于派生表的子查询将生成一个派生表
3.原方法的FROM后面添加的是表名,基于派生表的查询FROM后面必须要为派生关系指定一个别名

SELECT总结:

SELECT语句的一般格式:
在这里插入图片描述
整个SELECT语句的含义是,根据WHERE子句的条件表达式从FROM子句指定的基本表、视图或派生表中找到满足条件的元组,再按SELECT子句的目标列表达式选出元组中的属性形成结果表。
如果有GROUP BY子句,则将结果按<列名 1>的值进行分组,该属性列值相等的元组为一个组,通常会在每组中作用聚集函数。如果GROUP BY子句带HAVING短语,则只有满足指定条件的组才会输出。
如果有ORDER BY子句,则结果表还要按<列名 2>的值升序(ASC)或者降序(DESC)排序
SELECT可以进行简单的单表查询、连接查询、嵌套查询、集合查询和基于派生表的查询
查询满足指定条件的元组可以通过WHERE子句来实现
在这里插入图片描述
在SELECT中还可以使用聚集函数:
在这里插入图片描述
连接查询与单表查询不同,连接查询时同时涉及两个以上的表,连接查询分为等值连接查询与非等值连接查询。连接查询不仅可以在两个表之间进行还可以是一个表与其自身进行连接,称为表的自身连接,此时必须要为表取别名。
在SQL语言中,还可以进行嵌套查询,即将一个查询快嵌套在另一个查询快的WHERE子句或者HAVING短语的条件中。上层的查询块叫外层查询或父查询,下层的查询块称为内层查询或子查询。
带谓词的子查询:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
集合操作主要包括并操作UNION、交操作INTERSECT和差操作EXCEPT,但是参加集合操作的各查询结果的列数必须是相同的,对应项的数据类型也必须是相同的。
基于派生表的查询其实就是将出现在WHERE子句中的子查询经过适当的修改,使他出现在FROM子句中,同时FROM子句的子查询还会生成一个对应的派生表。

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

猜你喜欢

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