OUC中国海洋大学数据库系统SQL查询复习课件示例

单表查询

选择表中若干列

【例1】、【例2】、【例3】略

查询经过计算的值

主要是查询列里面进行运算,使用函数转换大小写,列别名

【例4】查全体学生的姓名及其出生年份

SELECT Sname, 2025-Sage
FROM Student

【例5】查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名

SELECT Sname,‘Year of Birth: ',2004-Sage,ISLOWER(Sdept)
FROM Student;

选择表中若干元组

image-20260114172223082

另外还有DISTNCT,消除重复的行。以及如果字符串匹配(LIKE)里有 ‘_’的话,使用转移字符 ‘\’。但是最后要加上 ESCAPE ‘\’

【例15】查询所有姓刘的同学的姓名、学号和性别

SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname LIKE ‘刘%’;

【例16】查询姓“欧阳”且全名为三个汉字的学生的姓名

SELECT Sname
FROM Student
WHERE Sname LIKE '欧阳_';

【例25】查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

Select *
FROM Student
Order by Sdept, Sage DESC

聚集函数

聚集函数有以下

作用 函数
计数 COUNT( [DISTINCT | ALL] * )
COUNT( [DISTINCT | ALL] <列名> )
计算总和 SUM ( [DISTINCT | ALL] <>)
计算平均 AVG
最大值 MAX
最小值 MIN

GROUP BY 子句

对查询结果分组,并且聚集函数将作用于每个组

【例31】求各个课程号及相应的选课人数

SELECT Cno, COUNT(Sno)
FROM SC
Group BY Cno;

【例32】查询选修了3们以上课程的学生学号

SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(Cno)>3;

连接查询

注意要避免歧义

自然连接

自身连接

【例35】查询每一门课的间接先修课

SELECT T2.Cpno
FROM Course T1, Course T2
Where T1.cpno = T2.cno;

外连接

外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出

【例36】查询所有学生(包括未选课)的成绩

SELECT Student.*
FROM Student
LEFT OUT JOIN SC ON (Student.Sno = SC.Sno);

复合条件连接

【例38】查询每个学生的学号、姓名、选修的课程名及成绩

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

嵌套查询

一个 SELECT-FROM-WHERE称为一个查询快,将一个查询块嵌套在另一个查询快的WHERE子句或HAVING短语的条件中的查询称为嵌套查询

子查询不能使用ORDER BY

包括带IN谓词的子查询带有比较运算符的子查询带有ANY ALL谓词的子查询带有EXISTS谓词的子查询。其中前三类可以用最后一类替换,但是最后一类不完全能被前三类替换。

ANY ALL

>ANY:大于子查询结果中的某一个值

>ALL:大于子查询中的所有值

!= 或 <> ANY:不等于子查询结果中的某一个值

!= 或 <> ALL:不等于子查询结果中的任何一个值

EXISTS

带有EXISTS谓词的子查询不返回任何数据,值产生逻辑真值“true”或逻辑假值“false”。由于不返回数据所以一般目标列表达式都用*

  • 若内层查询结果非空,则外层的WHERE子句返回真
  • 若内层查询结果为空,则外层的WHERE子句返回假

不相关子查询

由里向外 逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。

【例39】查询与“刘晨”在同一个系学习的学生。

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

如果只有一个系,那么这个IN可以替换成 =

同样也可以用带EXISTS的子查询做,这里的sql语句略了

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

连接查询

SELECT Student.Sno, Student.Sname
FROM Student,Course,SC
WHERE Student.sno = SC.sno
and Course.cno = SC.cno
and course.cname = '信息系统';

子查询

SELECT Student.Sno, Student.Sname
FROM Student
WHERE Student.sno IN(
	SELECT SC.sno
	FROM SC
	WHERE SC.cno IN(
		SELECT Course.cno
		FROM Course
		WHERE Course.cname = '信息系统'
	)
)

【例42】查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄

SELECT x.Sname,x.Sage
FROM Student x
WHERE x.Sdept != '计算机科学'
AND x.age < ANY(
	SELECT y.Sage
	FROM Student y
	WHERE y.Sdept = '计算机科学'
)

我们也可以理解成比计算机科学系学生的最大年龄小就可以了,所以可以使用MAX聚集函数。SQL语句这里就不说了

【例43】查询其他系中比计算机科学系所有学生年龄都小的学生姓名及年龄。

SELECT Sname, Sage
FROM Student
WHERE Student.Dept <> 'CS'
AND Student.age < ALL(
	SELECT Sage
	FROM Student
	WHERE Sdept = 'CS'
)

同样的,这里可以理解成比计算机系最小年龄还要小。

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

SELECT Sname
FROM Student
WHERE EXISTS(
	SELECT *
    FROM SC
    WHERE SC.sno = Student.sno
    AND SC.cno = '1'
);

一般我们是用多表连接查询了,所以没啥大必要

相关子查询

首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表。然后再取外层表的下一个元组

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

错误示例:

SELECT SC.sno, SC.cno
FROM SC x
WHERE x.Grade >= (
	SELECT AVG(SC.Grade)
    FROM SC y
    GROUP BY y.sno
);
  • 首先这里两个SC没有做区分,有歧义
  • 注意我们使用比较运算符的话,运算符前后一定要有可比性。在父查询中,我们使用Grade字段进行比较,是一个数 ,所以子查询得到的也一定是一个数字。而这里子查询得到的是一组平均数

我们想要从一组平均数中得到一个平均数,而这个平均数是父查询中选出来的来进行比较的这个人的,所以父查询和子查询应该建立联系,成为相关子查询

正确做法

SELECT x.Cno
FROM SC x
WHERE x.Grade >= (
	SELECT AVG(y.Grade)
    FROM SC y
    WHERE x.sno = y.sno
);
★【例46】查询选修了全部课程的学生姓名。

也就是说,不存在一门课,这个学生没有选

SELECT Sname
FROM Student
WHERE NOT Exists(
	SELECT *
	FROM Course
	WHERE Not Exists(
		SELECT * 
		FROM SC
		WHERE SC.cno = Course.cno
		AND SC.Sno = Student.Sno
	)
);

【例47】查询至少选修了学生200215122选修的全部课程的学生号码。

即不存在这样的课,200215122选修了但是sno没选修的。上面会了水到渠成了。我们可以这样理解,上一题的第二层循环中是我们从课程表中选出所有的课,这里第二层循环我们从选课表中选出学生200215122选出的所有课

SELECT x.Sno
FROM SC x
WHERE NOT EXISTS(
	SELECT *
	FROM SC y
	WHERE y.Sno='20025122'
	AND NOT EXISTS(
    	SELECT * 
        FROM SC z
        WHERE z.cno = y.cno
        AND z.sno = x.sno
    )
)

同样这里可以利用集合相减,比较巧妙。如果两个集合相同,那么相减为0:换到这里就是说sno选的课和200215122选的课构成的集合完全相同,那么except的结果就是0,我们需要这样的sno,所以使用NOT EXISTS

集合查询

集合相减

使用关键字:EXCEPT

懒得写哈哈,EXCEPT A也可以看作是AND !A。

集合相并

使用关键字:UNION [ALL]

使用UNION合并的时候自动去掉重复元组,加上ALL关键字保留

【例48】查询计算机科学系的学生及年龄不大于19岁的学生。

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

WHERE 子句用 OR 不好吗 哈哈。但是要记得加DISTINCT

集合相交

使用关键字:INTERSECT

【例50】查询计算机科学系的学生与年龄不大于19岁的学生的交集

太简单不写了。

posted @ 2026-01-21 14:52  Pocon  阅读(7)  评论(0)    收藏  举报