数据库作业7:SQL练习4 - SELECT(连接查询、嵌套查询)

一、连接查询
1、等值于非等值连接查询
在这里插入图片描述

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

学生情况存放在Student表中,学生选课情况存放在SC表中,所以本次查询涉及Student和SC两个表,这两个表之间的联系是通过公共属性Sno实现的。
查询结果:在这里插入图片描述
SELECT子句与WHERE子句的属性名前都加上了表名前缀,这是为了避免混淆。如果属性名在参加连接的各表中是唯一的(连接的表里只能一个表有!!!),则可以省略表名前缀。

在等值连接中,把目标列中重复的属性列去掉为自然连接。
在这里插入图片描述

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

在本例中,由于Student.Sno,Sname,Ssex,Sage,Sdept,Cno和Grade属性列在Student表和SC表中是唯一的,因此引用时可以去掉表名前缀,而Sno在两个表中都出现了,因此引用时必须加上表名前缀。
查询结果:在这里插入图片描述这样重复的Sno只留了一列。(不要care那个奇奇怪怪的S_entrance列)


一条SQL语句可以同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的复合条件。
在这里插入图片描述

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

我表里没有符合条件的人,所以不展示截图了。(如果你忘了写表名前缀的话,快接受批评!!!我可能是鱼的记忆)在这里插入图片描述


2、自身连接
连接操作不仅可以在两个表之间进行,还可以一个表与其自已进行连接,成为自身连接。
在这里插入图片描述
在Course表中只有每门课的直接先选课的信息,而没有先修课的先修课。要得到这个信息,必须先对一门课找到其先修课,再按此先修课的课程号查找它的先修课程,这就要将Course与其自身连接。
为此,要为Course表取两个别名,一个是FIRST,另一个是SECOND。

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

查询结果:在这里插入图片描述


3、外连接
例3.49中表里没有一些学生的信息,那是因为他们没有选课,在SC表中没有相应的元组,导致Student中这些没有选课的元组被舍弃了。
如果想即使没有选课,仍把Student的悬浮元组保存在结果关系中,而在SC表的属性上写NULL,这时就要使用外连接
改写例3.49:

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

查询结果:在这里插入图片描述,这样没有选课的两位同学也展示了出来。
左外连接列出左边关系中所有的元组(本例),右外连接列出右边关系中所有的元组。


4、多表连接
连接操作除了两表连接,自身链接外,还可以两个以上的表进行连接,称为多表连接。
在这里插入图片描述

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

查询结果:在这里插入图片描述
在执行多表连接时,通常是先进行两个表的连接操作,再将其连接结果与第三个表进行连接。


二、嵌套查询
①在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询
②上层的查询块称为外层查询或父查询,下层的查询块称为内层查询或子查询
③SQL语言允许多层嵌套查询,及一个子查询中还可以嵌套其他子查询。但是子查询的SELECT语句中不能使用ORDER BY子句,该子句只能对最终查询结果排序。
1、带有IN谓词的子查询
在这里插入图片描述
方法一(子查询的查询条件不依赖于父查询,称为不相关子查询):

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

方法二(由里向外处理,先进性子查询,子查询的结果用于建立其父查询的查找条件):

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN('CS');

方法三(用自身连接来完成):

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

查询结果都为:在这里插入图片描述
在这里插入图片描述
本题涉及了两个表Student表和Course表,但这两个表没有直接联系,所以要通过SC表建立联系,所以实际上就涉及了三个表的查询。

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

还可以用连接查询:

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

查询结果都为:在这里插入图片描述
但是有些嵌套查询可以用连接查询代替,有些就不可以。


2、带有比较运算符的子查询
带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。
在这里插入图片描述

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

x是表SC的别名,又称元组变量,可以用来表示SC的一个元组。内层查询是求一个学生所有选修课程平均成绩的,至于是那个学生的平均成绩要看参数x.Sno的值,而该值是与父查询相关的,因此这类查询称为相关子查询
查询结果:在这里插入图片描述


3、带有ANY(SOME)或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';

查询结果:在这里插入图片描述
这两个例子查询都可以用聚集函数来实现。

比如例3.59用聚集函数表示为:

SELECT Sname,Sage
FROM Student
WHERE Sage<
         (SELECT Min(Sage)
          FROM Student
		  WHERE Sdept='CS')
AND Sdept<>'CS';

查询结果相同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章