数据库系统概论|第三章:关系数据库标准语言SQL—课程笔记5

前言

在前文中,我们开始介绍了多表查询,即连接查询,同时简单的介绍了其中的一种形式,即等值连接查询与非等值连接查询,接下来我们将进行介绍连接查询中的另外几种常见形式。此外,本文还将介绍一些见到的嵌套查询以及集合查询。

注:本文中所涉及的数据库前文中已经介绍(指路:数据库系统概论|第三章:关系数据库标准语言SQL—课程笔记1

一、连接查询

1.等值连接与非等值连接

前文已经进行了介绍(指路:数据库系统概论|第三章:关系数据库标准语言SQL—课程笔记4

2.自身连接

连接操作不仅可以用于进行两个表之间的连接,同时也可以是一个表与其自己进行连接,此为表的自身连接。

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

上述代码便体现了如何在Course表中查询每一门课的间接先行课(即先行课中的先行课)【此代码中要注意自身连接中,要重读利用统一关系表,分别将原表命名为FIRST与SECOND,此后,再次进行对于这两个表的操作】

3.外连接

普通连接操作只输出满足连接条件的元组。外连接操作除返回满足连接条件的元组外,将主体表中不满足连接条件的元组也一并输出【空位用NULL值填充】。

  • 左外连接(LEFT (OUTER) JOIN ):将左表中不满足连接条件的元组也一并输出 。
  • 右外连接(RIGHT (OUTER) JOIN ) :将右表中不满足连接条件的元组也一并输出 。
  • 完整外部联接(FULL (OUTER) JOIN ):两个表不满足连接条件的元组也一并输出 。
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student  LEFT OUTER JOIN SC ON (Student.Sno = SC.Sno)

上述代码便体现了用左连接求每个学生的课程选修情况【上述结果中便保留了没有进行选课的同学】

如上图所示,王敏和张立的选课情况中,便显示为NULL值。

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

上述代码便体现了用全外连接求每个学生的课程选修情况【即左右两侧均可能有空值NULL的出现】

4.多表连接

除了上文中体现了量表连接以及自身连接之外,还可以是两表及两表以上的多表连接,其基本语句与上述查询相差不大

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

上述代码便体现了将我们所创建的三个基本表进行了总的连接

二、嵌套查询

一个SELECT-FROM-WHERE语句被称之为一个查询块,一个查询块嵌套在另一个查询块中的查询被称之为嵌套查询,此时,上层查询被称之为外层查询或者父查询,下层查询被称之为内层查询或者子查询。注:子查询的SELECT语句中不可以使用ORDER BY语句!

/*外层查询/父查询*/
SELECT Sname
FROM Student
WHERE Sno IN(
	 /*内层查询/子查询*/
	SELECT Sno
	FROM SC
	WHERE Cno = '2')

上述代码便体现了查询所有选修了课程2的学生的姓名【内外层查询分别分开,这里将子查询的查询结果作为了一个集合,并利用IN语句进行判断与选择】

——有关EXISTS子句的介绍

带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。

  • 若内层查询结果非空,则外层的WHERE子句返回真值;
  • 若内层查询结果为空,则外层的WHERE子句返回假值。
--求同时选修了1号和2号课程的学生学号
SELECT Sno FROM SC AS OUT WHERE Cno = '1'
	AND EXISTS(SELECT * FROM SC  WHERE OUT.Sno = SC.Sno AND Cno = '2' )

--求选修了1号但未选修2号课程的学生学号
SELECT * FROM SC AS OUT WHERE Cno = '1'
	AND NOT EXISTS(SELECT * FROM SC  WHERE OUT.Sno = SC.Sno AND Cno = '2' )

上述代码分别体现了EXISTS与NOT EXISTS语句的基本使用法则【但应注意同样的此处两次使用SC表,因此对他进行重命名以示区分】

注意嵌套查询中,一定要先从内层查询开始分析,进而分析外层查询。

三、集合查询

SELECT语句的查询结果是元组的集合,因此,可以利用有关集合的操作方法进行对于查询结果进行相关操作。有关集合的操作包含并操作(UNION)、交操作(INTERSECT)以及差操作(EXCEPT)。

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

上述代码为将‘CS’专业的学生集合与年龄不大于19岁的学生集合取并集。

此处,额外强调:

  • UNION:将多个查询结果合并起来时,系统自动去掉重复元组。
  • UNION ALL:将多个查询结果合并起来时,保留重复元组。
SELECT Sno
FROM SC
WHERE Cno = '1' AND 
Sno IN  (SELECT Sno
         FROM SC
         WHERE Cno = '2')

上述代码为选择课程1与选择课程2的学生的交集。

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

上述代码为将‘CS’专业的学生集合与年龄不大于19岁的学生集合的差集【即选择那些‘CS’系中年龄大于19岁的学生】。

下面来看一个较为综合性的题目,统计学生姓名中每一个字出现的总次数

--统计姓名中每个汉字出现的次数
SELECT Text, COUNT(*)   
FROM	(SELECT Substring(Sname,1,1) AS Text FROM Student WHERE LEN(Sname)>=1
		UNION ALL
		SELECT Substring(Sname,2,1) FROM Student WHERE LEN(Sname)>=2
		UNION ALL
		SELECT Substring(Sname,3,1) FROM Student WHERE LEN(Sname)>=3
		) AS T
GROUP BY Text

该代码较为综合,下面对其关键语句进行读取:

①COUNT:聚合计数函数,用于统计每一个字出现的次数

②Subtring:字符串截取函数,用于断开每一个字(从哪一位开始截取,截取长度为多少)

③LEN:字符串长度函数,用于判断姓名长度

④UNION ALL:集合的并,同时不消除重复项

上述代码的综合思想为:先将每一个人的姓名进行断开,每一个字单独充当一个元素,然后将这三个集合取并集,并将由这个并集构成的表命名为T,其中具有一个属性,为Text,然后根据该属性进行分组并计数即可。

四、小结

基于此,有关数据查询的相关代码已经全部讲解完毕,有关数据查询的基本代码框架如下:

 灵活运用这些基本语句,就可以实现大部分的数据查询操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值