OUC中国海洋大学数据库系统SQL查询复习课件示例
单表查询
选择表中若干列
【例1】、【例2】、【例3】略
查询经过计算的值
主要是查询列里面进行运算,使用函数转换大小写,列别名
【例4】查全体学生的姓名及其出生年份
SELECT Sname, 2025-Sage
FROM Student
【例5】查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名
SELECT Sname,‘Year of Birth: ',2004-Sage,ISLOWER(Sdept)
FROM Student;
选择表中若干元组

另外还有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岁的学生的交集
太简单不写了。

浙公网安备 33010602011771号