数据库系统概论第6版王珊版:第二章关系代数与第三章SQL期末重点整理

文章目录

  • 数据库系统概论第6版:第二章关系代数与第三章SQL期末重点整理
    • 一、三张表结构
      • [1. 课程表 Course](#1. 课程表 Course)
      • [2. 选课表 SC](#2. 选课表 SC)
      • [3. 学生表 Student](#3. 学生表 Student)
  • 二、第二章:关系代数重点
    • [1. 选择运算 σ:选行](#1. 选择运算 σ:选行)
      • [例 1:查询信息安全专业的学生](#例 1:查询信息安全专业的学生)
      • [例 2:查询男生信息](#例 2:查询男生信息)
      • [例 3:查询成绩大于等于 90 分的选课记录](#例 3:查询成绩大于等于 90 分的选课记录)
    • [2. 投影运算 π:选列](#2. 投影运算 π:选列)
      • [例 1:查询所有学生的学号和姓名](#例 1:查询所有学生的学号和姓名)
      • [例 2:查询所有课程的课程号、课程名和学分](#例 2:查询所有课程的课程号、课程名和学分)
      • [例 3:查询所有开课学期](#例 3:查询所有开课学期)
    • [3. 选择 + 投影组合](#3. 选择 + 投影组合)
      • [例 1:查询信息安全专业学生的姓名](#例 1:查询信息安全专业学生的姓名)
      • [例 2:查询 81001 课程的选课学生学号和成绩](#例 2:查询 81001 课程的选课学生学号和成绩)
      • [例 3:查询学分为 4 的课程名](#例 3:查询学分为 4 的课程名)
    • [4. 笛卡尔积 ×](#4. 笛卡尔积 ×)
    • [5. 连接运算 ⋈](#5. 连接运算 ⋈)
      • [例 1:查询学生姓名、课程号和成绩](#例 1:查询学生姓名、课程号和成绩)
      • [例 2:查询学生姓名、课程名和成绩](#例 2:查询学生姓名、课程名和成绩)
      • [例 3:查询选修"数据库系统概论"的学生姓名和成绩](#例 3:查询选修“数据库系统概论”的学生姓名和成绩)
      • [例 4:查询李勇选修的课程名和成绩](#例 4:查询李勇选修的课程名和成绩)
    • [6. 自然连接](#6. 自然连接)
    • [7. 并运算 ∪](#7. 并运算 ∪)
    • [8. 差运算 -](#8. 差运算 -)
      • [例 1:查询没有选课的学生学号](#例 1:查询没有选课的学生学号)
      • [例 2:查询没有选修 81001 课程的学生学号](#例 2:查询没有选修 81001 课程的学生学号)
      • [例 3:查询选修了 81001 但没有选修 81002 的学生学号](#例 3:查询选修了 81001 但没有选修 81002 的学生学号)
    • [9. 除法运算 ÷](#9. 除法运算 ÷)
      • [例 1:查询选修了全部课程的学生学号](#例 1:查询选修了全部课程的学生学号)
      • [例 2:查询至少选修了 20180001 号学生所选全部课程的学生学号](#例 2:查询至少选修了 20180001 号学生所选全部课程的学生学号)
  • [三、第三章:SQL 查询重点](#三、第三章:SQL 查询重点)
    • [1. 基本查询](#1. 基本查询)
      • [例 1:查询所有学生信息](#例 1:查询所有学生信息)
      • [例 2:查询所有课程信息](#例 2:查询所有课程信息)
      • [例 3:查询所有选课记录](#例 3:查询所有选课记录)
    • [2. DISTINCT 去重查询](#2. DISTINCT 去重查询)
    • [3. WHERE 条件查询](#3. WHERE 条件查询)
      • [例 1:查询计算机科学与技术专业的学生](#例 1:查询计算机科学与技术专业的学生)
      • [例 2:查询成绩低于 60 分的选课记录](#例 2:查询成绩低于 60 分的选课记录)
      • [例 3:查询 20201 学期的选课记录](#例 3:查询 20201 学期的选课记录)
    • [4. BETWEEN 查询](#4. BETWEEN 查询)
      • [例:查询成绩在 80 到 90 分之间的选课记录](#例:查询成绩在 80 到 90 分之间的选课记录)
    • [5. IN 查询](#5. IN 查询)
      • [例:查询课程号为 81001、81002、81003 的课程信息](#例:查询课程号为 81001、81002、81003 的课程信息)
    • [6. LIKE 模糊查询](#6. LIKE 模糊查询)
    • [7. NULL 查询](#7. NULL 查询)
    • [8. ORDER BY 排序](#8. ORDER BY 排序)
  • 四、多表连接查询
    • [1. 查询每个学生的选课情况](#1. 查询每个学生的选课情况)
    • [2. 查询每门课的选课学生姓名](#2. 查询每门课的选课学生姓名)
    • [3. 查询 81001 课程的学生姓名和成绩](#3. 查询 81001 课程的学生姓名和成绩)
    • [4. 查询"程序设计基础与C语言"课程的学生姓名和成绩](#4. 查询“程序设计基础与C语言”课程的学生姓名和成绩)
    • [5. 查询李勇的所有课程名和成绩](#5. 查询李勇的所有课程名和成绩)
  • 五、聚集函数与关系代数说明
    • [1. 查询学生总人数](#1. 查询学生总人数)
    • [2. 查询每门课的平均成绩](#2. 查询每门课的平均成绩)
    • [3. 查询每个学生的平均成绩](#3. 查询每个学生的平均成绩)
    • [4. 查询 81001 课程的最高分](#4. 查询 81001 课程的最高分)
    • [5. 查询每门课的选课人数](#5. 查询每门课的选课人数)
    • [6. 查询选课人数超过 2 人的课程号](#6. 查询选课人数超过 2 人的课程号)
  • 六、嵌套查询
    • [1. IN 子查询](#1. IN 子查询)
      • [例:查询选修了 81001 课程的学生姓名](#例:查询选修了 81001 课程的学生姓名)
    • [2. NOT EXISTS 子查询](#2. NOT EXISTS 子查询)
      • [例:查询没有选修 81001 课程的学生姓名](#例:查询没有选修 81001 课程的学生姓名)
    • [3. EXISTS 子查询](#3. EXISTS 子查询)
    • [4. 查询没有选任何课程的学生姓名](#4. 查询没有选任何课程的学生姓名)
  • 七、"全部"类题型
    • [1. 查询选修了全部课程的学生姓名](#1. 查询选修了全部课程的学生姓名)
    • [2. 查询至少选修了李勇所选全部课程的学生姓名](#2. 查询至少选修了李勇所选全部课程的学生姓名)
    • [3. 查询至少选修了 20180001 号学生所选全部课程的学生姓名](#3. 查询至少选修了 20180001 号学生所选全部课程的学生姓名)
  • 八、常见期末大题模板
    • [1. 查询"选修了某门课"的学生](#1. 查询“选修了某门课”的学生)
    • [2. 查询"没有选修某门课"的学生](#2. 查询“没有选修某门课”的学生)
    • [3. 查询"某学生选修的课程"](#3. 查询“某学生选修的课程”)
    • [4. 查询"选修了全部课程"的学生](#4. 查询“选修了全部课程”的学生)
  • 九、易错点总结
    • [1. 关系代数投影默认去重,SQL 默认不去重](#1. 关系代数投影默认去重,SQL 默认不去重)
    • [2. WHERE 和 HAVING 不要混用](#2. WHERE 和 HAVING 不要混用)
    • [3. NULL 不能用等号判断](#3. NULL 不能用等号判断)
    • [4. 自然连接不要乱用](#4. 自然连接不要乱用)
  • 十、考前速记

课程表(Course)

选课表(SC)

学生表(Student)

数据库系统概论第6版:第二章关系代数与第三章SQL期末重点整理

本文按照以下三张表整理:

Course(Cno, Cname, Credit, Cpno)

SC(Sno, Cno, Grade, Semester, Teachingclass)

Student(Sno, Sname, Sex, Birthday, Smajor)

说明:本文每个关系代数表达式都配对应 SQL,每个 SQL 也配对应关系代数表达式。

关系代数主要对应 SQL 查询语句,CREATE / INSERT / UPDATE / DELETE 没有直接的关系代数等价式,本文重点整理期末最常考的查询部分。


一、三张表结构

1. 课程表 Course

text 复制代码
Course(Cno, Cname, Credit, Cpno)
字段 含义
Cno 课程号
Cname 课程名
Credit 学分
Cpno 先修课号

2. 选课表 SC

text 复制代码
SC(Sno, Cno, Grade, Semester, Teachingclass)
字段 含义
Sno 学号
Cno 课程号
Grade 成绩
Semester 学期
Teachingclass 教学班

3. 学生表 Student

text 复制代码
Student(Sno, Sname, Sex, Birthday, Smajor)
字段 含义
Sno 学号
Sname 姓名
Sex 性别
Birthday 出生日期
Smajor 专业

二、第二章:关系代数重点

关系代数常考运算:

text 复制代码
选择 σ
投影 π
并 ∪
差 -
笛卡尔积 ×
连接 ⋈
自然连接 ⋈
除法 ÷

关系代数与 SQL 的大致对应关系:

关系代数 SQL
σ WHERE
π SELECT
× FROM 多表
JOIN ON
UNION
- NOT EXISTS / NOT IN
÷ 双重 NOT EXISTS

1. 选择运算 σ:选行

选择运算用于从表中选出满足条件的元组。

例 1:查询信息安全专业的学生

关系代数:

text 复制代码
σ Smajor='信息安全'(Student)

SQL:

sql 复制代码
SELECT *
FROM Student
WHERE Smajor = '信息安全';

例 2:查询男生信息

关系代数:

text 复制代码
σ Sex='男'(Student)

SQL:

sql 复制代码
SELECT *
FROM Student
WHERE Sex = '男';

例 3:查询成绩大于等于 90 分的选课记录

关系代数:

text 复制代码
σ Grade>=90(SC)

SQL:

sql 复制代码
SELECT *
FROM SC
WHERE Grade >= 90;

2. 投影运算 π:选列

投影运算用于选出指定属性列。

例 1:查询所有学生的学号和姓名

关系代数:

text 复制代码
π Sno,Sname(Student)

SQL:

sql 复制代码
SELECT DISTINCT Sno, Sname
FROM Student;

注意:

text 复制代码
关系代数的投影默认去重,SQL 默认不去重。
如果要和关系代数严格一致,SQL 应使用 DISTINCT。

例 2:查询所有课程的课程号、课程名和学分

关系代数:

text 复制代码
π Cno,Cname,Credit(Course)

SQL:

sql 复制代码
SELECT DISTINCT Cno, Cname, Credit
FROM Course;

例 3:查询所有开课学期

关系代数:

text 复制代码
π Semester(SC)

SQL:

sql 复制代码
SELECT DISTINCT Semester
FROM SC;

3. 选择 + 投影组合

期末最常见的关系代数题通常是选择和投影组合。

例 1:查询信息安全专业学生的姓名

关系代数:

text 复制代码
π Sname(σ Smajor='信息安全'(Student))

SQL:

sql 复制代码
SELECT DISTINCT Sname
FROM Student
WHERE Smajor = '信息安全';

例 2:查询 81001 课程的选课学生学号和成绩

关系代数:

text 复制代码
π Sno,Grade(σ Cno='81001'(SC))

SQL:

sql 复制代码
SELECT DISTINCT Sno, Grade
FROM SC
WHERE Cno = '81001';

例 3:查询学分为 4 的课程名

关系代数:

text 复制代码
π Cname(σ Credit=4(Course))

SQL:

sql 复制代码
SELECT DISTINCT Cname
FROM Course
WHERE Credit = 4;

4. 笛卡尔积 ×

笛卡尔积会把两个关系中的元组两两组合。

单独考得不多,通常配合选择运算构造连接。

例:查询学生姓名和其选课成绩

关系代数:

text 复制代码
π Sname,Cno,Grade(σ Student.Sno=SC.Sno(Student × SC))

SQL:

sql 复制代码
SELECT DISTINCT Student.Sname, SC.Cno, SC.Grade
FROM Student, SC
WHERE Student.Sno = SC.Sno;

5. 连接运算 ⋈

连接运算是多表查询的核心。

例 1:查询学生姓名、课程号和成绩

关系代数:

text 复制代码
π Sname,Cno,Grade(Student ⋈ Student.Sno=SC.Sno SC)

SQL:

sql 复制代码
SELECT DISTINCT S.Sname, SC.Cno, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno;

例 2:查询学生姓名、课程名和成绩

关系代数:

text 复制代码
π Sname,Cname,Grade((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course)

SQL:

sql 复制代码
SELECT DISTINCT S.Sname, C.Cname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno;

例 3:查询选修"数据库系统概论"的学生姓名和成绩

关系代数:

text 复制代码
π Sname,Grade(σ Cname='数据库系统概论'((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course))

SQL:

sql 复制代码
SELECT DISTINCT S.Sname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE C.Cname = '数据库系统概论';

例 4:查询李勇选修的课程名和成绩

关系代数:

text 复制代码
π Cname,Grade(σ Sname='李勇'((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course))

SQL:

sql 复制代码
SELECT DISTINCT C.Cname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE S.Sname = '李勇';

6. 自然连接

自然连接会自动按照两个关系中同名属性进行连接。

StudentSC 有同名属性 Sno,可以自然连接。

SCCourse 有同名属性 Cno,也可以自然连接。

例:查询学生姓名、课程名和成绩

关系代数:

text 复制代码
π Sname,Cname,Grade(Student ⋈ SC ⋈ Course)

SQL:

sql 复制代码
SELECT DISTINCT Sname, Cname, Grade
FROM Student
NATURAL JOIN SC
NATURAL JOIN Course;

考试提醒:

text 复制代码
自然连接会自动按所有同名字段连接。
如果不确定同名字段是否唯一,建议用 JOIN ON 写清楚连接条件。

等价的更稳妥写法:

关系代数:

text 复制代码
π Sname,Cname,Grade((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course)

SQL:

sql 复制代码
SELECT DISTINCT S.Sname, C.Cname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno;

7. 并运算 ∪

并运算用于合并两个查询结果。

例:查询信息安全专业或数据科学与大数据技术专业的学生学号

关系代数:

text 复制代码
π Sno(σ Smajor='信息安全'(Student)) ∪ π Sno(σ Smajor='数据科学与大数据技术'(Student))

SQL:

sql 复制代码
SELECT Sno
FROM Student
WHERE Smajor = '信息安全'
UNION
SELECT Sno
FROM Student
WHERE Smajor = '数据科学与大数据技术';

也可以写成:

关系代数:

text 复制代码
π Sno(σ Smajor='信息安全' OR Smajor='数据科学与大数据技术'(Student))

SQL:

sql 复制代码
SELECT DISTINCT Sno
FROM Student
WHERE Smajor = '信息安全'
   OR Smajor = '数据科学与大数据技术';

8. 差运算 -

差运算常用于表达"没有""未选""不属于"。

例 1:查询没有选课的学生学号

关系代数:

text 复制代码
π Sno(Student) - π Sno(SC)

SQL:

sql 复制代码
SELECT S.Sno
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC
    WHERE SC.Sno = S.Sno
);

例 2:查询没有选修 81001 课程的学生学号

关系代数:

text 复制代码
π Sno(Student) - π Sno(σ Cno='81001'(SC))

SQL:

sql 复制代码
SELECT S.Sno
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC
    WHERE SC.Sno = S.Sno
      AND SC.Cno = '81001'
);

例 3:查询选修了 81001 但没有选修 81002 的学生学号

关系代数:

text 复制代码
π Sno(σ Cno='81001'(SC)) - π Sno(σ Cno='81002'(SC))

SQL:

sql 复制代码
SELECT SC1.Sno
FROM SC SC1
WHERE SC1.Cno = '81001'
  AND NOT EXISTS (
      SELECT *
      FROM SC SC2
      WHERE SC2.Sno = SC1.Sno
        AND SC2.Cno = '81002'
  );

9. 除法运算 ÷

除法是期末难点,常用于表达:

text 复制代码
全部
所有
至少包含全部

例 1:查询选修了全部课程的学生学号

关系代数:

text 复制代码
π Sno,Cno(SC) ÷ π Cno(Course)

SQL:

sql 复制代码
SELECT S.Sno
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM Course C
    WHERE NOT EXISTS (
        SELECT *
        FROM SC
        WHERE SC.Sno = S.Sno
          AND SC.Cno = C.Cno
    )
);

理解:

text 复制代码
不存在一门课程,该学生没有选修。

例 2:查询至少选修了 20180001 号学生所选全部课程的学生学号

关系代数:

text 复制代码
π Sno,Cno(SC) ÷ π Cno(σ Sno='20180001'(SC))

SQL:

sql 复制代码
SELECT S.Sno
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC SC1
    WHERE SC1.Sno = '20180001'
      AND NOT EXISTS (
          SELECT *
          FROM SC SC2
          WHERE SC2.Sno = S.Sno
            AND SC2.Cno = SC1.Cno
      )
);

理解:

text 复制代码
不存在一门 20180001 选过的课,而该学生没有选。

三、第三章:SQL 查询重点

第三章 SQL 最核心的内容是查询。下面所有 SQL 都给出对应关系代数。


1. 基本查询

例 1:查询所有学生信息

SQL:

sql 复制代码
SELECT *
FROM Student;

关系代数:

text 复制代码
Student

例 2:查询所有课程信息

SQL:

sql 复制代码
SELECT *
FROM Course;

关系代数:

text 复制代码
Course

例 3:查询所有选课记录

SQL:

sql 复制代码
SELECT *
FROM SC;

关系代数:

text 复制代码
SC

2. DISTINCT 去重查询

例:查询所有专业名称

SQL:

sql 复制代码
SELECT DISTINCT Smajor
FROM Student;

关系代数:

text 复制代码
π Smajor(Student)

3. WHERE 条件查询

例 1:查询计算机科学与技术专业的学生

SQL:

sql 复制代码
SELECT *
FROM Student
WHERE Smajor = '计算机科学与技术';

关系代数:

text 复制代码
σ Smajor='计算机科学与技术'(Student)

例 2:查询成绩低于 60 分的选课记录

SQL:

sql 复制代码
SELECT *
FROM SC
WHERE Grade < 60;

关系代数:

text 复制代码
σ Grade<60(SC)

例 3:查询 20201 学期的选课记录

SQL:

sql 复制代码
SELECT *
FROM SC
WHERE Semester = '20201';

关系代数:

text 复制代码
σ Semester='20201'(SC)

4. BETWEEN 查询

例:查询成绩在 80 到 90 分之间的选课记录

SQL:

sql 复制代码
SELECT *
FROM SC
WHERE Grade BETWEEN 80 AND 90;

关系代数:

text 复制代码
σ Grade>=80 AND Grade<=90(SC)

5. IN 查询

例:查询课程号为 81001、81002、81003 的课程信息

SQL:

sql 复制代码
SELECT *
FROM Course
WHERE Cno IN ('81001', '81002', '81003');

关系代数:

text 复制代码
σ Cno='81001' OR Cno='81002' OR Cno='81003'(Course)

6. LIKE 模糊查询

例:查询课程名中包含"数据库"的课程

SQL:

sql 复制代码
SELECT *
FROM Course
WHERE Cname LIKE '%数据库%';

关系代数:

text 复制代码
σ Cname LIKE '%数据库%'(Course)

说明:

text 复制代码
严格的传统关系代数中没有 LIKE,这是 SQL 的字符串匹配条件。
考试中可把 LIKE 当作选择条件写在 σ 中。

7. NULL 查询

例:查询没有先修课的课程

SQL:

sql 复制代码
SELECT *
FROM Course
WHERE Cpno IS NULL;

关系代数:

text 复制代码
σ Cpno IS NULL(Course)

注意:

text 复制代码
NULL 不能写成 = NULL,必须写 IS NULL。

8. ORDER BY 排序

关系代数本身是集合运算,不强调顺序,因此传统关系代数没有排序运算。

考试中如果要求 SQL 和关系代数互译,排序通常只在 SQL 中体现。

例:查询选课记录,按成绩降序排列

SQL:

sql 复制代码
SELECT *
FROM SC
ORDER BY Grade DESC;

关系代数:

text 复制代码
SC

补充说明:

text 复制代码
ORDER BY 是 SQL 的显示排序要求,传统关系代数不表达结果顺序。

四、多表连接查询


1. 查询每个学生的选课情况

SQL:

sql 复制代码
SELECT S.Sno, S.Sname, SC.Cno, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno;

关系代数:

text 复制代码
π Student.Sno,Sname,Cno,Grade(Student ⋈ Student.Sno=SC.Sno SC)

2. 查询每门课的选课学生姓名

SQL:

sql 复制代码
SELECT C.Cname, S.Sname
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno;

关系代数:

text 复制代码
π Cname,Sname((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course)

3. 查询 81001 课程的学生姓名和成绩

SQL:

sql 复制代码
SELECT S.Sname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
WHERE SC.Cno = '81001';

关系代数:

text 复制代码
π Sname,Grade(σ Cno='81001'(Student ⋈ Student.Sno=SC.Sno SC))

4. 查询"程序设计基础与C语言"课程的学生姓名和成绩

SQL:

sql 复制代码
SELECT S.Sname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE C.Cname = '程序设计基础与C语言';

关系代数:

text 复制代码
π Sname,Grade(σ Cname='程序设计基础与C语言'((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course))

5. 查询李勇的所有课程名和成绩

SQL:

sql 复制代码
SELECT C.Cname, SC.Grade
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE S.Sname = '李勇';

关系代数:

text 复制代码
π Cname,Grade(σ Sname='李勇'((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course))

五、聚集函数与关系代数说明

SQL 中的聚集函数包括:

text 复制代码
COUNT
SUM
AVG
MAX
MIN

传统关系代数不直接包含聚集函数。

不过数据库课程中有时会使用扩展关系代数,用 γ 表示分组和聚集。

下面用扩展关系代数表示。


1. 查询学生总人数

SQL:

sql 复制代码
SELECT COUNT(*) AS StudentCount
FROM Student;

扩展关系代数:

text 复制代码
γ COUNT(*)→StudentCount(Student)

2. 查询每门课的平均成绩

SQL:

sql 复制代码
SELECT Cno, AVG(Grade) AS AvgGrade
FROM SC
GROUP BY Cno;

扩展关系代数:

text 复制代码
γ Cno; AVG(Grade)→AvgGrade(SC)

3. 查询每个学生的平均成绩

SQL:

sql 复制代码
SELECT Sno, AVG(Grade) AS AvgGrade
FROM SC
GROUP BY Sno;

扩展关系代数:

text 复制代码
γ Sno; AVG(Grade)→AvgGrade(SC)

4. 查询 81001 课程的最高分

SQL:

sql 复制代码
SELECT MAX(Grade) AS MaxGrade
FROM SC
WHERE Cno = '81001';

扩展关系代数:

text 复制代码
γ MAX(Grade)→MaxGrade(σ Cno='81001'(SC))

5. 查询每门课的选课人数

SQL:

sql 复制代码
SELECT Cno, COUNT(*) AS Num
FROM SC
GROUP BY Cno;

扩展关系代数:

text 复制代码
γ Cno; COUNT(*)→Num(SC)

6. 查询选课人数超过 2 人的课程号

SQL:

sql 复制代码
SELECT Cno
FROM SC
GROUP BY Cno
HAVING COUNT(*) > 2;

扩展关系代数:

text 复制代码
π Cno(σ Num>2(γ Cno; COUNT(*)→Num(SC)))

六、嵌套查询


1. IN 子查询

例:查询选修了 81001 课程的学生姓名

SQL:

sql 复制代码
SELECT Sname
FROM Student
WHERE Sno IN (
    SELECT Sno
    FROM SC
    WHERE Cno = '81001'
);

关系代数:

text 复制代码
π Sname(Student ⋈ Student.Sno=SC.Sno σ Cno='81001'(SC))

也可以写成:

text 复制代码
π Sname(σ Cno='81001'(Student ⋈ Student.Sno=SC.Sno SC))

2. NOT EXISTS 子查询

例:查询没有选修 81001 课程的学生姓名

SQL:

sql 复制代码
SELECT Sname
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC
    WHERE SC.Sno = S.Sno
      AND SC.Cno = '81001'
);

关系代数:

text 复制代码
π Sname(Student ⋈ (π Sno(Student) - π Sno(σ Cno='81001'(SC))))

更清晰地写成两步:

text 复制代码
T = π Sno(Student) - π Sno(σ Cno='81001'(SC))
π Sname(Student ⋈ T)

3. EXISTS 子查询

例:查询至少选修了一门课程的学生姓名

SQL:

sql 复制代码
SELECT Sname
FROM Student S
WHERE EXISTS (
    SELECT *
    FROM SC
    WHERE SC.Sno = S.Sno
);

关系代数:

text 复制代码
π Sname(Student ⋈ Student.Sno=SC.Sno SC)

4. 查询没有选任何课程的学生姓名

SQL:

sql 复制代码
SELECT Sname
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC
    WHERE SC.Sno = S.Sno
);

关系代数:

text 复制代码
T = π Sno(Student) - π Sno(SC)
π Sname(Student ⋈ T)

七、"全部"类题型

看到:

text 复制代码
所有
全部
每一门
至少包含全部

优先想到:

text 复制代码
关系代数:除法 ÷
SQL:双重 NOT EXISTS

1. 查询选修了全部课程的学生姓名

SQL:

sql 复制代码
SELECT Sname
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM Course C
    WHERE NOT EXISTS (
        SELECT *
        FROM SC
        WHERE SC.Sno = S.Sno
          AND SC.Cno = C.Cno
    )
);

关系代数:

text 复制代码
T = π Sno,Cno(SC) ÷ π Cno(Course)
π Sname(Student ⋈ T)

2. 查询至少选修了李勇所选全部课程的学生姓名

SQL:

sql 复制代码
SELECT S2.Sname
FROM Student S2
WHERE NOT EXISTS (
    SELECT *
    FROM SC SC1
    JOIN Student S1 ON SC1.Sno = S1.Sno
    WHERE S1.Sname = '李勇'
      AND NOT EXISTS (
          SELECT *
          FROM SC SC2
          WHERE SC2.Sno = S2.Sno
            AND SC2.Cno = SC1.Cno
      )
);

关系代数:

text 复制代码
T1 = π Cno(σ Sname='李勇'(Student ⋈ Student.Sno=SC.Sno SC))
T2 = π Sno,Cno(SC) ÷ T1
π Sname(Student ⋈ T2)

3. 查询至少选修了 20180001 号学生所选全部课程的学生姓名

SQL:

sql 复制代码
SELECT S.Sname
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC SC1
    WHERE SC1.Sno = '20180001'
      AND NOT EXISTS (
          SELECT *
          FROM SC SC2
          WHERE SC2.Sno = S.Sno
            AND SC2.Cno = SC1.Cno
      )
);

关系代数:

text 复制代码
T = π Sno,Cno(SC) ÷ π Cno(σ Sno='20180001'(SC))
π Sname(Student ⋈ T)

八、常见期末大题模板

1. 查询"选修了某门课"的学生

SQL 模板:

sql 复制代码
SELECT S.Sname
FROM Student S
JOIN SC ON S.Sno = SC.Sno
WHERE SC.Cno = '课程号';

关系代数模板:

text 复制代码
π Sname(σ Cno='课程号'(Student ⋈ Student.Sno=SC.Sno SC))

2. 查询"没有选修某门课"的学生

SQL 模板:

sql 复制代码
SELECT S.Sname
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM SC
    WHERE SC.Sno = S.Sno
      AND SC.Cno = '课程号'
);

关系代数模板:

text 复制代码
T = π Sno(Student) - π Sno(σ Cno='课程号'(SC))
π Sname(Student ⋈ T)

3. 查询"某学生选修的课程"

SQL 模板:

sql 复制代码
SELECT C.Cname
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE S.Sname = '学生姓名';

关系代数模板:

text 复制代码
π Cname(σ Sname='学生姓名'((Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course))

4. 查询"选修了全部课程"的学生

SQL 模板:

sql 复制代码
SELECT S.Sname
FROM Student S
WHERE NOT EXISTS (
    SELECT *
    FROM Course C
    WHERE NOT EXISTS (
        SELECT *
        FROM SC
        WHERE SC.Sno = S.Sno
          AND SC.Cno = C.Cno
    )
);

关系代数模板:

text 复制代码
T = π Sno,Cno(SC) ÷ π Cno(Course)
π Sname(Student ⋈ T)

九、易错点总结

1. 关系代数投影默认去重,SQL 默认不去重

关系代数:

text 复制代码
π Smajor(Student)

SQL 应写:

sql 复制代码
SELECT DISTINCT Smajor
FROM Student;

2. WHERE 和 HAVING 不要混用

SQL:

sql 复制代码
SELECT Cno, COUNT(*) AS Num
FROM SC
GROUP BY Cno
HAVING COUNT(*) > 2;

扩展关系代数:

text 复制代码
σ Num>2(γ Cno; COUNT(*)→Num(SC))

3. NULL 不能用等号判断

SQL:

sql 复制代码
SELECT *
FROM Course
WHERE Cpno IS NULL;

关系代数:

text 复制代码
σ Cpno IS NULL(Course)

错误写法:

sql 复制代码
WHERE Cpno = NULL

4. 自然连接不要乱用

自然连接:

text 复制代码
Student ⋈ SC ⋈ Course

对应 SQL:

sql 复制代码
SELECT *
FROM Student
NATURAL JOIN SC
NATURAL JOIN Course;

更推荐写清楚连接条件:

关系代数:

text 复制代码
(Student ⋈ Student.Sno=SC.Sno SC) ⋈ SC.Cno=Course.Cno Course

SQL:

sql 复制代码
SELECT *
FROM Student S
JOIN SC ON S.Sno = SC.Sno
JOIN Course C ON SC.Cno = C.Cno;

十、考前速记

text 复制代码
σ 是选择,对应 WHERE,负责选行。
π 是投影,对应 SELECT,负责选列。
× 是笛卡尔积,多表组合。
⋈ 是连接,对应 JOIN ON。
∪ 是并,对应 UNION。
- 是差,常用 NOT EXISTS 表示"没有"。
÷ 是除法,常用双重 NOT EXISTS 表示"全部"。

看到"没有",想到差运算和 NOT EXISTS。
看到"全部",想到除法和双重 NOT EXISTS。
看到"每门课平均成绩",想到 GROUP BY 和 AVG。
看到"选课人数超过多少",想到 GROUP BY 和 HAVING。
相关推荐
TDengine (老段)1 小时前
TDengine 数据保留与 TTL — 多级存储、过期删除与分层迁移
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
安当加密03011 小时前
等保2.0三级数据库加密:2026检查清单 + TDE部署实战(附脚本)
数据库·网络安全·数据安全·tde·等保2.0·数据库加密·tde透明加密
解决问题no解决代码问题1 小时前
TiDB 原理与节点宕机实战讲解
数据库·tidb
禅思院1 小时前
大列表性能优化 · 面试精讲 · 一
面试·职场和发展·性能优化
江湖中的阿龙1 小时前
Redis 五大核心数据类型底层原理
数据库·redis·缓存
茫忙然1 小时前
Claude Code 接入 DeepSeek 或 多模型 教程(Linux)
java·linux·数据库
AI人工智能+电脑小能手10 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
yyuuuzz10 小时前
独立站的技术基础与常见运维问题
大数据·运维·服务器·网络·数据库·aws
键盘上的猫头鹰13 小时前
【MySQL 教程(八)】索引、事务、用户管理、导入导出与分页查询
数据库·python·mysql