数据库(三):关系代数

关系代数详解

关系代数是关系数据库的理论基础,提供了一套完整的数据查询操作集合。本文详细介绍关系代数的八种基本运算及其数学表示。


目录

  • [第一章 关系代数概述](#第一章 关系代数概述)
  • [第二章 传统集合运算](#第二章 传统集合运算)
  • [第三章 专门关系运算](#第三章 专门关系运算)
  • [第四章 扩展关系运算](#第四章 扩展关系运算)
  • [第五章 运算符优先级与表达式](#第五章 运算符优先级与表达式)
  • [第六章 关系代数与SQL对照](#第六章 关系代数与SQL对照)
  • [第七章 综合练习与案例](#第七章 综合练习与案例)
  • [第八章 面试与考试重点](#第八章 面试与考试重点)

第一章 关系代数概述

关系代数是关系数据库的理论基础,理解它对于深入掌握SQL和数据库查询优化至关重要。

1.1 什么是关系代数

定义

关系代数(Relational Algebra) 是一种抽象的查询语言,它使用对关系的运算来表达查询。简单来说:

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    关系代数的本质                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  输入:一个或多个关系(表)                                     │
│         ↓                                                       │
│  运算:对关系进行各种操作                                       │
│         ↓                                                       │
│  输出:一个新的关系(表)                                       │
│                                                                 │
│  核心思想:关系进 → 关系出(封闭性)                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
起源
  • 1970年:E.F. Codd 在其经典论文中提出关系模型
  • 关系代数是Codd为关系模型定义的两种形式化查询语言之一
  • 另一种是关系演算(Relational Calculus)
与关系演算的区别
比较项 关系代数 关系演算
性质 过程化语言 非过程化语言
描述方式 "如何做" "要什么"
操作方式 指定运算步骤 只描述结果条件
理论基础 集合论 谓词逻辑
类比 像菜谱(步骤) 像点菜(结果)

通俗理解:

  • 关系代数:告诉数据库"先做A,再做B,最后做C"
  • 关系演算:告诉数据库"我要满足X条件的数据"
在数据库中的地位
复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    关系代数的重要性                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. SQL的理论基础                                               │
│     • SQL是基于关系代数和关系演算设计的                         │
│     • 理解关系代数有助于写出更好的SQL                           │
│                                                                 │
│  2. 查询优化的基础                                              │
│     • 数据库优化器使用关系代数规则进行查询优化                  │
│     • 等价变换规则用于生成更高效的执行计划                      │
│                                                                 │
│  3. 数据库理论的核心                                            │
│     • 证明查询等价性                                            │
│     • 分析查询复杂度                                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.2 关系代数的分类

关系代数的运算可以分为三大类:

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    运算分类                                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  一、传统集合运算(基于集合论)                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 并(Union)         ∪    合并两个关系的元组           │   │
│  │ • 交(Intersection)  ∩    取两个关系的公共元组         │   │
│  │ • 差(Difference)    -    从R中去除S中也有的元组       │   │
│  │ • 笛卡尔积(Product) ×    所有元组的组合               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  二、专门关系运算(为关系数据库设计)                            │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 选择(Selection)   σ    按条件选择行(水平切分)     │   │
│  │ • 投影(Projection)  π    选择列(垂直切分)           │   │
│  │ • 连接(Join)        ⋈    关联两个关系                 │   │
│  │ • 除法(Division)    ÷    "全部"类型查询               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  三、扩展运算(实际应用扩展)                                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 外连接(Outer Join)     保留不匹配的元组             │   │
│  │ • 半连接(Semi Join)      只返回匹配的一侧             │   │
│  │ • 聚集(Aggregation)      COUNT, SUM, AVG等            │   │
│  │ • 分组(Grouping)         GROUP BY操作                 │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

五种基本运算:

在八种运算中,以下五种是基本运算,其他运算都可以由它们表示:

基本运算 符号 说明
合并元组
- 去除元组
笛卡尔积 × 组合元组
选择 σ 选择行
投影 π 选择列

交、连接、除法都可用这五种基本运算表示

1.3 关系代数的基本符号

关系与元组符号
复制代码
基本符号约定:

┌──────────────────┬────────────────────────────────────────────┐
│ 符号             │ 含义                                       │
├──────────────────┼────────────────────────────────────────────┤
│ R, S, T          │ 关系(表)的名称                           │
├──────────────────┼────────────────────────────────────────────┤
│ t, u, v          │ 元组(行)                                 │
├──────────────────┼────────────────────────────────────────────┤
│ A, B, C          │ 属性(列)名称                             │
├──────────────────┼────────────────────────────────────────────┤
│ a₁, a₂, ...      │ 属性的替代表示                             │
├──────────────────┼────────────────────────────────────────────┤
│ t[A]             │ 元组t在属性A上的值                         │
├──────────────────┼────────────────────────────────────────────┤
│ t ∈ R            │ 元组t属于关系R                             │
├──────────────────┼────────────────────────────────────────────┤
│ |R|              │ 关系R的元组数(基数)                      │
└──────────────────┴────────────────────────────────────────────┘
运算符号速查表
运算 符号 读法 类型 输入 输出
Union 二元 两个关系 一个关系
Intersection 二元 两个关系 一个关系
- Difference 二元 两个关系 一个关系
笛卡尔积 × Cross Product 二元 两个关系 一个关系
选择 σ Sigma 一元 一个关系 一个关系
投影 π Pi 一元 一个关系 一个关系
连接 Bowtie 二元 两个关系 一个关系
÷ Division 二元 两个关系 一个关系
示例关系

后续章节将使用以下示例关系来说明各种运算:

复制代码
学生表 Student:                   课程表 Course:
┌─────┬──────┬─────┐              ┌─────┬──────────┬─────┐
│ Sno │ Name │ Age │              │ Cno │ Cname    │ Credit│
├─────┼──────┼─────┤              ├─────┼──────────┼─────┤
│ S1  │ 张三 │ 20  │              │ C1  │ 数据库   │ 4   │
│ S2  │ 李四 │ 21  │              │ C2  │ 数学     │ 3   │
│ S3  │ 王五 │ 19  │              │ C3  │ 英语     │ 2   │
└─────┴──────┴─────┘              └─────┴──────────┴─────┘

选课表 SC(学生-课程关系):
┌─────┬─────┬───────┐
│ Sno │ Cno │ Grade │
├─────┼─────┼───────┤
│ S1  │ C1  │ 90    │
│ S1  │ C2  │ 85    │
│ S2  │ C1  │ 88    │
│ S2  │ C3  │ 78    │
│ S3  │ C2  │ 92    │
└─────┴─────┴───────┘

第二章 传统集合运算

传统集合运算来源于数学中的集合论,是关系代数的基础运算。这些运算要求参与运算的两个关系必须具有相同的目(属性个数相同,对应属性的域相容)。

2.1 并运算(Union)

2.1.1 定义

并运算 是将两个关系的所有元组合并成一个关系,同时去除重复元组

复制代码
通俗理解:
把两个表的数据"合并"在一起,相同的行只保留一份。
就像把两个班级的学生名单合并成一个年级名单。

运算前提(并相容条件):

  • R和S的属性个数相同(目相同)
  • 对应属性的域相同(或可相互转换)
2.1.2 符号表示
复制代码
R ∪ S = { t | t ∈ R ∨ t ∈ S }

读作:R并S等于所有属于R或属于S的元组t的集合
2.1.3 性质
性质 表达式 说明
交换律 R ∪ S = S ∪ R 顺序不影响结果
结合律 (R ∪ S) ∪ T = R ∪ (S ∪ T) 可以任意组合
幂等律 R ∪ R = R 自己并自己还是自己
零元素 R ∪ ∅ = R 并上空集不变
2.1.4 示例
复制代码
关系R(班级A学生):            关系S(班级B学生):
┌─────┬──────┬─────┐           ┌─────┬──────┬─────┐
│ Sno │ Name │ Age │           │ Sno │ Name │ Age │
├─────┼──────┼─────┤           ├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │           │ S2  │ 李四 │ 21  │
│ S2  │ 李四 │ 21  │           │ S4  │ 赵六 │ 20  │
│ S3  │ 王五 │ 19  │           │ S5  │ 孙七 │ 22  │
└─────┴──────┴─────┘           └─────┴──────┴─────┘

R ∪ S(合并两个班级):
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │
│ S2  │ 李四 │ 21  │  ← S2李四只出现一次(去重)
│ S3  │ 王五 │ 19  │
│ S4  │ 赵六 │ 20  │
│ S5  │ 孙七 │ 22  │
└─────┴──────┴─────┘
结果:5个元组(不是6个,因为S2重复)

对应SQL:

sql 复制代码
SELECT * FROM R
UNION
SELECT * FROM S;

2.2 交运算(Intersection)

2.2.1 定义

交运算 是取两个关系的公共元组,即同时出现在两个关系中的元组。

复制代码
通俗理解:
找出两个表中"完全相同"的行。
就像找出同时参加了两个社团的学生。

运算前提: R和S必须并相容

2.2.2 符号表示
复制代码
R ∩ S = { t | t ∈ R ∧ t ∈ S }

读作:R交S等于所有既属于R又属于S的元组t的集合
2.2.3 性质
性质 表达式 说明
交换律 R ∩ S = S ∩ R 顺序不影响结果
结合律 (R ∩ S) ∩ T = R ∩ (S ∩ T) 可以任意组合
幂等律 R ∩ R = R 自己交自己还是自己
零元素 R ∩ ∅ = ∅ 交上空集为空
2.2.4 可用差运算表示

交运算不是基本运算,可以用差运算表示:

复制代码
R ∩ S = R - (R - S)

推导:
  R - S     = R中有但S中没有的元组
  R - (R-S) = R中去掉"R有S没有的"= R和S都有的 = R ∩ S
2.2.5 示例
复制代码
关系R:                         关系S:
┌─────┬──────┬─────┐           ┌─────┬──────┬─────┐
│ Sno │ Name │ Age │           │ Sno │ Name │ Age │
├─────┼──────┼─────┤           ├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │           │ S2  │ 李四 │ 21  │
│ S2  │ 李四 │ 21  │           │ S4  │ 赵六 │ 20  │
│ S3  │ 王五 │ 19  │           │ S5  │ 孙七 │ 22  │
└─────┴──────┴─────┘           └─────┴──────┴─────┘

R ∩ S(两个班级都有的学生):
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S2  │ 李四 │ 21  │  ← 只有李四同时在两个班级
└─────┴──────┴─────┘
结果:1个元组

对应SQL:

sql 复制代码
SELECT * FROM R
INTERSECT
SELECT * FROM S;

2.3 差运算(Difference)

2.3.1 定义

差运算 是从关系R中去除也在关系S中出现的元组,保留R中独有的元组。

复制代码
通俗理解:
找出只在第一个表中有,第二个表中没有的行。
就像找出只参加了社团A但没参加社团B的学生。

运算前提: R和S必须并相容

2.3.2 符号表示
复制代码
R - S = { t | t ∈ R ∧ t ∉ S }

读作:R减S等于所有属于R但不属于S的元组t的集合
2.3.3 性质
性质 表达式 说明
不满足交换律 R - S ≠ S - R 顺序会影响结果!
不满足结合律 (R - S) - T ≠ R - (S - T) 不能任意组合
零元素 R - ∅ = R 减去空集不变
自反 R - R = ∅ 自己减自己为空

注意:差运算是五种基本运算之一,也是唯一不满足交换律的集合运算!

2.3.4 示例
复制代码
关系R:                         关系S:
┌─────┬──────┬─────┐           ┌─────┬──────┬─────┐
│ Sno │ Name │ Age │           │ Sno │ Name │ Age │
├─────┼──────┼─────┤           ├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │           │ S2  │ 李四 │ 21  │
│ S2  │ 李四 │ 21  │           │ S4  │ 赵六 │ 20  │
│ S3  │ 王五 │ 19  │           │ S5  │ 孙七 │ 22  │
└─────┴──────┴─────┘           └─────┴──────┴─────┘

R - S(只在班级A不在班级B的学生):
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │
│ S3  │ 王五 │ 19  │
└─────┴──────┴─────┘

S - R(只在班级B不在班级A的学生):
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S4  │ 赵六 │ 20  │
│ S5  │ 孙七 │ 22  │
└─────┴──────┴─────┘

注意:R - S ≠ S - R!

对应SQL:

sql 复制代码
SELECT * FROM R
EXCEPT       -- 或 MINUS(Oracle语法)
SELECT * FROM S;

2.4 笛卡尔积(Cartesian Product)

2.4.1 定义

笛卡尔积 是将两个关系的每一个元组进行所有可能的组合

复制代码
通俗理解:
把两个表的每一行都两两配对,生成所有可能的组合。
就像学生表和课程表的笛卡尔积 = 每个学生配每门课程。

结果特点:

  • 若R有n个属性、m₁个元组
  • 若S有k个属性、m₂个元组
  • R × S 有 n+k个属性m₁ × m₂个元组
2.4.2 符号表示
复制代码
R × S = { t₁t₂ | t₁ ∈ R ∧ t₂ ∈ S }

读作:R叉乘S等于R中每个元组与S中每个元组连接而成的新元组的集合
2.4.3 性质
性质 表达式 说明
交换律 R × S ≈ S × R 元组相同,属性顺序不同
结合律 (R × S) × T = R × (S × T) 可以任意组合
分配律 R × (S ∪ T) = (R × S) ∪ (R × T) 对并运算分配
2.4.4 示例
复制代码
关系R(学生):                  关系S(课程):
┌─────┬──────┐                  ┌─────┬──────┐
│ Sno │ Name │                  │ Cno │ Cname│
├─────┼──────┤                  ├─────┼──────┤
│ S1  │ 张三 │                  │ C1  │ 数据库│
│ S2  │ 李四 │                  │ C2  │ 数学  │
└─────┴──────┘                  └─────┴──────┘
  2个元组                          2个元组

R × S(笛卡尔积):
┌─────┬──────┬─────┬──────┐
│ Sno │ Name │ Cno │ Cname│
├─────┼──────┼─────┼──────┤
│ S1  │ 张三 │ C1  │ 数据库│   ← S1配C1
│ S1  │ 张三 │ C2  │ 数学  │   ← S1配C2
│ S2  │ 李四 │ C1  │ 数据库│   ← S2配C1
│ S2  │ 李四 │ C2  │ 数学  │   ← S2配C2
└─────┴──────┴─────┴──────┘
  结果:2+2=4个属性,2×2=4个元组

重要说明:

笛卡尔积本身很少单独使用,因为结果包含大量无意义的组合。它通常与选择运算 结合使用来实现连接运算

复制代码
连接 = 笛卡尔积 + 选择

自然连接 R ⋈ S = σ(等值条件)(R × S)

对应SQL:

sql 复制代码
SELECT * FROM R, S;              -- 隐式笛卡尔积
SELECT * FROM R CROSS JOIN S;    -- 显式笛卡尔积

本章小结

复制代码
传统集合运算总结:

┌─────────────┬────────┬───────────────────────────────────────┐
│ 运算        │ 符号   │ 要点                                  │
├─────────────┼────────┼───────────────────────────────────────┤
│ 并          │ ∪      │ 合并去重,需并相容                    │
├─────────────┼────────┼───────────────────────────────────────┤
│ 交          │ ∩      │ 取公共,可用差表示                    │
├─────────────┼────────┼───────────────────────────────────────┤
│ 差          │ -      │ 取独有,不满足交换律!                │
├─────────────┼────────┼───────────────────────────────────────┤
│ 笛卡尔积    │ ×      │ 元组数相乘,属性数相加                │
└─────────────┴────────┴───────────────────────────────────────┘

基本运算:并、差、笛卡尔积(交可以用差表示)

第三章 专门关系运算

专门关系运算是专门为关系数据库设计的运算,包括选择、投影、连接和除法。这些运算是关系代数的核心,也是SQL查询的理论基础。

3.1 选择运算(Selection / Restriction)

3.1.1 定义

选择运算 是从关系R中选取满足指定条件的元组,形成一个新的关系。

复制代码
通俗理解:
选择就是"筛选行",保留满足条件的行,去掉不满足条件的行。
就像在学生表中筛选出"年龄大于20岁"的学生。

┌──────────────────────────────────────────────────────────────┐
│  选择运算的效果:水平切分(行选择)                          │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  原始关系R:               选择后 σ_F(R):                   │
│  ┌─────┬─────┬─────┐      ┌─────┬─────┬─────┐               │
│  │ A   │ B   │ C   │      │ A   │ B   │ C   │               │
│  ├─────┼─────┼─────┤      ├─────┼─────┼─────┤               │
│  │ ... │ ... │ ... │  →   │ ... │ ... │ ... │ ← 满足条件    │
│  │ ... │ ... │ ... │      │ ... │ ... │ ... │ ← 满足条件    │
│  │ ... │ ... │ ... │      └─────┴─────┴─────┘               │
│  └─────┴─────┴─────┘                                        │
│                          (列不变,行减少)                  │
└──────────────────────────────────────────────────────────────┘
3.1.2 符号表示
复制代码
σ_F(R) = { t | t ∈ R ∧ F(t) = true }

读作:Sigma F of R
含义:从关系R中选择满足条件F的所有元组t

其中:

  • σ(sigma)是选择运算符
  • F 是选择条件(谓词)
  • R 是关系名
3.1.3 条件表达式F

选择条件F由以下元素构成:

类型 运算符 含义
比较运算符 >, <, =, ≥, ≤, ≠ 属性与常量或属性比较
逻辑运算符 ∧(AND),∨(OR),¬(NOT) 组合多个条件

条件格式:

  • 简单条件:属性 θ 常量属性 θ 属性
  • 复合条件:使用∧、∨、¬组合简单条件
3.1.4 性质
性质 表达式 说明
级联选择 σ_F1(σ_F2®) = σ_F1∧F2® 多个选择可合并
选择交换 σ_F1(σ_F2®) = σ_F2(σ_F1®) 顺序可交换
选择与投影 σ_F(π_A®) = π_A(σ_F®)(当F只涉及A中的属性) 条件允许时可交换
选择与笛卡尔积 σ_F(R × S) = σ_F® × S(当F只涉及R的属性) 可下推到单个关系
3.1.5 示例
复制代码
学生表 Student:
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │
│ S2  │ 李四 │ 21  │
│ S3  │ 王五 │ 19  │
│ S4  │ 赵六 │ 22  │
└─────┴──────┴─────┘

查询1:选择年龄大于20的学生
σ_Age>20(Student)
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S2  │ 李四 │ 21  │
│ S4  │ 赵六 │ 22  │
└─────┴──────┴─────┘

查询2:选择年龄大于20且学号以S开头的学生
σ_Age>20 ∧ Sno='S2'(Student)
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S2  │ 李四 │ 21  │
└─────┴──────┴─────┘

对应SQL:

sql 复制代码
-- 查询1
SELECT * FROM Student WHERE Age > 20;

-- 查询2
SELECT * FROM Student WHERE Age > 20 AND Sno = 'S2';

3.2 投影运算(Projection)

3.2.1 定义

投影运算 是从关系R中选取指定的属性列,形成一个新的关系。

复制代码
通俗理解:
投影就是"选择列",只保留需要的列,其他列去掉。
同时会自动去除结果中的重复元组。

┌──────────────────────────────────────────────────────────────┐
│  投影运算的效果:垂直切分(列选择)                          │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  原始关系R:               投影后 π_A,B(R):                 │
│  ┌─────┬─────┬─────┐      ┌─────┬─────┐                     │
│  │ A   │ B   │ C   │      │ A   │ B   │  ← 只保留A、B列     │
│  ├─────┼─────┼─────┤      ├─────┼─────┤                     │
│  │ ... │ ... │ ... │  →   │ ... │ ... │                     │
│  │ ... │ ... │ ... │      │ ... │ ... │                     │
│  │ ... │ ... │ ... │      └─────┴─────┘                     │
│  └─────┴─────┴─────┘                                        │
│                          (行可能减少-去重,列减少)         │
└──────────────────────────────────────────────────────────────┘
3.2.2 符号表示
复制代码
π_A(R) = { t[A] | t ∈ R }

读作:Pi A of R
含义:从关系R中选择属性集A对应的列

其中:

  • π(pi)是投影运算符
  • A 是属性名列表(如 A₁, A₂, ..., Aₙ)
  • t[A] 表示元组t在属性集A上的分量
3.2.3 性质
性质 表达式 说明
级联投影 π_A(π_B®) = π_A®,其中A ⊆ B 投影的投影等于小的投影
投影交换 π_A(R ∪ S) = π_A® ∪ π_A(S) 对并运算分配

重要说明: 投影会自动去除重复元组,这是关系代数的基本要求(关系是集合)。

3.2.4 示例
复制代码
学生表 Student:
┌─────┬──────┬─────┐
│ Sno │ Name │ Age │
├─────┼──────┼─────┤
│ S1  │ 张三 │ 20  │
│ S2  │ 李四 │ 21  │
│ S3  │ 王五 │ 19  │
│ S4  │ 张三 │ 22  │  ← 注意:有两个张三
└─────┴──────┴─────┘

查询1:投影学号和姓名
π_Sno,Name(Student)
┌─────┬──────┐
│ Sno │ Name │
├─────┼──────┤
│ S1  │ 张三 │
│ S2  │ 李四 │
│ S3  │ 王五 │
│ S4  │ 张三 │
└─────┴──────┘

查询2:只投影姓名
π_Name(Student)
┌──────┐
│ Name │
├──────┤
│ 张三 │  ← 两个张三只保留一个!
│ 李四 │
│ 王五 │
└──────┘
结果只有3个元组(去重)

对应SQL:

sql 复制代码
-- 查询1
SELECT Sno, Name FROM Student;

-- 查询2(去重)
SELECT DISTINCT Name FROM Student;

注意: SQL中需要使用DISTINCT来去重,而关系代数中投影自动去重。


3.3 连接运算(Join)

连接是关系代数中最重要的运算,用于关联两个关系。

3.3.1 θ连接(Theta Join)
定义

θ连接是从两个关系的笛卡尔积中选取满足特定条件的元组。

复制代码
R ⋈_{AθB} S = σ_{AθB}(R × S)

其中θ是比较运算符(>、<、=、≥、≤、≠)
通俗理解
复制代码
θ连接 = 笛卡尔积 + 选择

先把两个表所有组合列出来(笛卡尔积),
再筛选出满足条件的行(选择)。
示例
复制代码
关系R:                关系S:
┌────┬────┐           ┌────┬────┐
│ A  │ B  │           │ C  │ D  │
├────┼────┤           ├────┼────┤
│ 1  │ 2  │           │ 2  │ x  │
│ 3  │ 4  │           │ 4  │ y  │
└────┴────┘           └────┴────┘

R ⋈_{B<C} S(B小于C的连接):
┌────┬────┬────┬────┐
│ A  │ B  │ C  │ D  │
├────┼────┼────┼────┤
│ 1  │ 2  │ 4  │ y  │  ← 2 < 4
└────┴────┴────┴────┘
3.3.2 等值连接(Equi-Join)
定义

等值连接是θ为等号(=)的θ连接。

复制代码
R ⋈_{A=B} S = σ_{A=B}(R × S)
特点
  • θ为等号
  • 结果中保留两个连接属性(都保留)
示例
复制代码
关系R:                关系S:
┌────┬────┐           ┌────┬────┐
│ A  │ B  │           │ B  │ C  │
├────┼────┤           ├────┼────┤
│ 1  │ 2  │           │ 2  │ x  │
│ 3  │ 4  │           │ 4  │ y  │
└────┴────┘           └────┴────┘

R ⋈_{R.B=S.B} S(等值连接):
┌────┬─────┬─────┬────┐
│ A  │ R.B │ S.B │ C  │
├────┼─────┼─────┼────┤
│ 1  │ 2   │ 2   │ x  │
│ 3  │ 4   │ 4   │ y  │
└────┴─────┴─────┴────┘
注意:B列出现两次!
3.3.3 自然连接(Natural Join)
定义

自然连接 是等值连接的特殊情况

  1. 自动在所有同名属性上进行等值连接

  2. 结果中去除重复的连接属性列

    R ⋈ S

    不需要指定连接条件,自动使用同名属性

通俗理解
复制代码
自然连接 = 等值连接 + 去除重复列

自动找两个表的同名列进行匹配,
结果中同名列只保留一份。
性质
性质 表达式 说明
交换律 R ⋈ S = S ⋈ R 顺序不影响结果
结合律 (R ⋈ S) ⋈ T = R ⋈ (S ⋈ T) 可以任意组合
示例
复制代码
学生表 Student:              选课表 SC:
┌─────┬──────┬─────┐         ┌─────┬─────┬───────┐
│ Sno │ Name │ Age │         │ Sno │ Cno │ Grade │
├─────┼──────┼─────┤         ├─────┼─────┼───────┤
│ S1  │ 张三 │ 20  │         │ S1  │ C1  │ 90    │
│ S2  │ 李四 │ 21  │         │ S1  │ C2  │ 85    │
│ S3  │ 王五 │ 19  │         │ S2  │ C1  │ 88    │
└─────┴──────┴─────┘         └─────┴─────┴───────┘

Student ⋈ SC(自然连接):
┌─────┬──────┬─────┬─────┬───────┐
│ Sno │ Name │ Age │ Cno │ Grade │
├─────┼──────┼─────┼─────┼───────┤
│ S1  │ 张三 │ 20  │ C1  │ 90    │
│ S1  │ 张三 │ 20  │ C2  │ 85    │
│ S2  │ 李四 │ 21  │ C1  │ 88    │
└─────┴──────┴─────┴─────┴───────┘

说明:
- 在同名属性Sno上进行等值连接
- Sno列只出现一次(去重)
- S3没有选课记录,所以不在结果中

对应SQL:

sql 复制代码
-- 自然连接
SELECT * FROM Student NATURAL JOIN SC;

-- 等价的显式连接
SELECT Student.Sno, Name, Age, Cno, Grade
FROM Student INNER JOIN SC ON Student.Sno = SC.Sno;
3.3.4 连接类型对比
复制代码
连接类型关系:

┌─────────────────────────────────────────────────────────────────┐
│                    连接类型层次                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  θ连接                    ← 最通用(任意比较条件)              │
│    ↓                                                            │
│  等值连接                 ← θ为等号的θ连接                      │
│    ↓                                                            │
│  自然连接                 ← 等值连接 + 去重复列 + 自动匹配同名列│
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

3.4 除运算(Division)

3.4.1 定义

除运算 用于查询"与S中所有元组都有关系"的R中的数据。

复制代码
通俗理解:
除法用于回答"全部"、"所有"类型的问题。

例如:"查询选修了所有课程的学生"

设:

  • R(X, Y):关系R有属性集X和Y
  • S(Y):关系S只有属性集Y(Y是R和S的公共属性)
  • R ÷ S:结果只包含X属性
3.4.2 符号表示
复制代码
R ÷ S = { t[X] | t ∈ R ∧ π_Y(S) ⊆ Y_x }

其中 Y_x = { t[Y] | t ∈ R ∧ t[X] = x }

通俗解释:

  • Y_x 是R中与x相关联的所有Y值的集合
  • 如果S中的所有Y值都在Y_x中,则x在结果中
3.4.3 等价表示(用基本运算)
复制代码
R ÷ S = π_X(R) - π_X((π_X(R) × S) - R)

推导过程:
1. π_X(R):R中所有可能的X值
2. π_X(R) × S:X与S的所有组合("应该有"的所有关系)
3. (π_X(R) × S) - R:R中缺少的关系
4. π_X(...):缺少关系的X值
5. π_X(R) - ...:去掉"缺少关系的X"= 与S完全匹配的X
3.4.4 适用场景

除法运算适用于包含以下关键词的查询:

  • "所有"
  • "全部"
  • "每一个"
  • "至少包含...中的所有"
3.4.5 示例
复制代码
选课表 SC:                    课程表 AllCourses:
┌─────┬─────┐                 ┌─────┐
│ Sno │ Cno │                 │ Cno │
├─────┼─────┤                 ├─────┤
│ S1  │ C1  │                 │ C1  │
│ S1  │ C2  │                 │ C2  │
│ S1  │ C3  │                 │ C3  │
│ S2  │ C1  │                 └─────┘
│ S2  │ C2  │
│ S3  │ C1  │
│ S3  │ C3  │
└─────┴─────┘

问题:查询选修了所有课程(C1, C2, C3)的学生

SC ÷ AllCourses = ?

分析:
- S1选了C1, C2, C3(全部3门)✓
- S2选了C1, C2(缺C3)✗
- S3选了C1, C3(缺C2)✗

结果:
┌─────┐
│ Sno │
├─────┤
│ S1  │  ← 只有S1选了所有课程
└─────┘

验证过程:

复制代码
步骤1:π_Sno(SC) = {S1, S2, S3}

步骤2:π_Sno(SC) × AllCourses = 
       {(S1,C1), (S1,C2), (S1,C3),
        (S2,C1), (S2,C2), (S2,C3),
        (S3,C1), (S3,C2), (S3,C3)}

步骤3:(π_Sno(SC) × AllCourses) - SC = 
       {(S2,C3), (S3,C2)}  ← S2缺C3,S3缺C2

步骤4:π_Sno(...) = {S2, S3}  ← 有缺失的学生

步骤5:π_Sno(SC) - ... = {S1}  ← 没有缺失的学生 = 结果

对应SQL:

sql 复制代码
-- 方法1:使用NOT EXISTS
SELECT DISTINCT Sno
FROM SC SC1
WHERE NOT EXISTS (
    SELECT Cno FROM AllCourses
    WHERE Cno NOT IN (
        SELECT Cno FROM SC SC2 WHERE SC2.Sno = SC1.Sno
    )
);

-- 方法2:使用COUNT
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(DISTINCT Cno) = (SELECT COUNT(*) FROM AllCourses);

本章小结

复制代码
专门关系运算总结:

┌─────────────┬────────┬───────────────────────────────────────┐
│ 运算        │ 符号   │ 要点                                  │
├─────────────┼────────┼───────────────────────────────────────┤
│ 选择        │ σ      │ 水平切分,按条件选行                  │
├─────────────┼────────┼───────────────────────────────────────┤
│ 投影        │ π      │ 垂直切分,选列并去重                  │
├─────────────┼────────┼───────────────────────────────────────┤
│ 连接        │ ⋈      │ 关联两表,自然连接最常用              │
├─────────────┼────────┼───────────────────────────────────────┤
│ 除法        │ ÷      │ "全部"类型查询                        │
└─────────────┴────────┴───────────────────────────────────────┘

基本运算:选择、投影(连接和除法可用基本运算表示)

最重要:选择 + 投影 + 自然连接 = 90%的查询需求

第四章 扩展关系运算

扩展关系运算是在基本关系代数基础上发展出来的,用于处理更复杂的实际需求。这些运算在现代SQL中都有对应实现。

4.1 外连接(Outer Join)

普通连接(内连接)只保留匹配的元组,而外连接可以保留不匹配的元组。

复制代码
通俗理解:
内连接:只取两边都有对应的数据
外连接:保留一边或两边不匹配的数据,用NULL填充
4.1.1 左外连接(Left Outer Join)

定义: 保留左侧关系R的所有元组,右侧S中无匹配的用NULL填充

符号: R ⟕ S

复制代码
学生表 Student:              选课表 SC:
┌─────┬──────┐               ┌─────┬─────┐
│ Sno │ Name │               │ Sno │ Cno │
├─────┼──────┤               ├─────┼─────┤
│ S1  │ 张三 │               │ S1  │ C1  │
│ S2  │ 李四 │               │ S1  │ C2  │
│ S3  │ 王五 │               │ S2  │ C1  │
└─────┴──────┘               └─────┴─────┘

Student ⟕ SC(左外连接):
┌─────┬──────┬─────┐
│ Sno │ Name │ Cno │
├─────┼──────┼─────┤
│ S1  │ 张三 │ C1  │
│ S1  │ 张三 │ C2  │
│ S2  │ 李四 │ C1  │
│ S3  │ 王五 │ NULL│  ← S3没选课,Cno为NULL
└─────┴──────┴─────┘
保留了所有学生,包括未选课的S3

对应SQL:

sql 复制代码
SELECT * FROM Student LEFT OUTER JOIN SC ON Student.Sno = SC.Sno;
4.1.2 右外连接(Right Outer Join)

定义: 保留右侧关系S的所有元组,左侧R中无匹配的用NULL填充

符号: R ⟖ S

复制代码
Student ⟖ SC(右外连接):
保留SC中的所有记录,Student中无匹配的用NULL填充

对应SQL:

sql 复制代码
SELECT * FROM Student RIGHT OUTER JOIN SC ON Student.Sno = SC.Sno;
4.1.3 全外连接(Full Outer Join)

定义: 保留两侧关系的所有元组,任一侧无匹配的都用NULL填充

符号: R ⟗ S

复制代码
R ⟗ S = (R ⟕ S) ∪ (R ⟖ S)

全外连接 = 左外连接 ∪ 右外连接

对应SQL:

sql 复制代码
SELECT * FROM Student FULL OUTER JOIN SC ON Student.Sno = SC.Sno;
外连接对比图
复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    外连接类型对比                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  内连接 ⋈:      R ∩ S(只取交集部分)                          │
│                                                                 │
│  左外连接 ⟕:    R 全部 + S 中匹配的部分                        │
│                                                                 │
│  右外连接 ⟖:    R 中匹配的部分 + S 全部                        │
│                                                                 │
│  全外连接 ⟗:    R 全部 + S 全部(并集)                        │
│                                                                 │
│         ┌──────────┐   ┌──────────┐                            │
│    R:  │ ████████ │   │ ████████ │ :S                        │
│         │    ┌─────┼───┼─────┐    │                            │
│         │    │     │   │     │    │                            │
│         │    │ 内连│接 │     │    │                            │
│         │    │     │   │     │    │                            │
│         │    └─────┼───┼─────┘    │                            │
│         │ 左外     │   │     右外 │                            │
│         └──────────┘   └──────────┘                            │
│            └─────────────────────┘                             │
│                    全外连接                                     │
└─────────────────────────────────────────────────────────────────┘

4.2 半连接(Semi-Join)

定义: 返回R中与S能连接的元组,但只保留R的属性

符号: R ⋉ S

复制代码
R ⋉ S = π_R(R ⋈ S)

只返回R中能与S匹配的行,不包含S的任何属性

示例:

复制代码
Student ⋉ SC = 返回有选课记录的学生(只保留Student的列)

结果:
┌─────┬──────┐
│ Sno │ Name │
├─────┼──────┤
│ S1  │ 张三 │
│ S2  │ 李四 │
└─────┴──────┘
(S3没有选课记录,不在结果中)

对应SQL:

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

4.3 反连接(Anti-Join)

定义: 返回R中与S不能连接的元组

符号: R ▷ S

复制代码
R ▷ S = R - (R ⋉ S)

返回R中无法与S匹配的行

示例:

复制代码
Student ▷ SC = 返回没有选课记录的学生

结果:
┌─────┬──────┐
│ Sno │ Name │
├─────┼──────┤
│ S3  │ 王五 │  ← 只有S3没选课
└─────┴──────┘

对应SQL:

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

4.4 聚集运算(Aggregation)

定义: 对关系的某属性值进行统计计算

符号: ℱ_F® 或 G_F®

常用聚集函数:

函数 含义 示例
COUNT 计数 COUNT(*) 或 COUNT(A)
SUM 求和 SUM(Grade)
AVG 平均值 AVG(Grade)
MAX 最大值 MAX(Grade)
MIN 最小值 MIN(Grade)

示例:

复制代码
选课表 SC:
┌─────┬─────┬───────┐
│ Sno │ Cno │ Grade │
├─────┼─────┼───────┤
│ S1  │ C1  │ 90    │
│ S1  │ C2  │ 85    │
│ S2  │ C1  │ 88    │
│ S2  │ C3  │ 78    │
└─────┴─────┴───────┘

ℱ_COUNT(*)(SC) = 4          -- 总记录数
ℱ_AVG(Grade)(SC) = 85.25    -- 平均成绩
ℱ_MAX(Grade)(SC) = 90       -- 最高成绩

对应SQL:

sql 复制代码
SELECT COUNT(*), AVG(Grade), MAX(Grade) FROM SC;

4.5 分组运算(Grouping)

定义: 按指定属性分组,然后对每组应用聚集函数

符号: γ_A,F® 或 G A ℱ F®

其中:

  • A 是分组属性
  • F 是聚集函数

示例:

复制代码
选课表 SC:
┌─────┬─────┬───────┐
│ Sno │ Cno │ Grade │
├─────┼─────┼───────┤
│ S1  │ C1  │ 90    │
│ S1  │ C2  │ 85    │
│ S2  │ C1  │ 88    │
│ S2  │ C3  │ 78    │
└─────┴─────┴───────┘

按学生分组,计算每个学生的平均成绩:
γ_Sno, AVG(Grade)(SC)

结果:
┌─────┬───────────┐
│ Sno │ AVG(Grade)│
├─────┼───────────┤
│ S1  │ 87.5      │  ← (90+85)/2
│ S2  │ 83.0      │  ← (88+78)/2
└─────┴───────────┘

对应SQL:

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

4.6 重命名运算(Rename)

定义: 为关系或属性指定新名称

符号: ρ_S(A1,A2,...)® 或 ρ_S®

用途:

  • 自连接时区分同一关系的两个实例
  • 使表达式更清晰

示例:

复制代码
查询所有学生对(不同学生的两两组合)
需要自连接,使用重命名区分:

ρ_R1(Student) ⋈_{R1.Sno < R2.Sno} ρ_R2(Student)

对应SQL:

sql 复制代码
SELECT R1.*, R2.*
FROM Student R1, Student R2
WHERE R1.Sno < R2.Sno;

本章小结

复制代码
扩展关系运算总结:

┌─────────────┬────────┬───────────────────────────────────────┐
│ 运算        │ 符号   │ 要点                                  │
├─────────────┼────────┼───────────────────────────────────────┤
│ 左外连接    │ ⟕      │ 保留左表全部,右表无匹配用NULL        │
├─────────────┼────────┼───────────────────────────────────────┤
│ 右外连接    │ ⟖      │ 保留右表全部,左表无匹配用NULL        │
├─────────────┼────────┼───────────────────────────────────────┤
│ 全外连接    │ ⟗      │ 保留两表全部                          │
├─────────────┼────────┼───────────────────────────────────────┤
│ 半连接      │ ⋉      │ 只返回能匹配的左表元组                │
├─────────────┼────────┼───────────────────────────────────────┤
│ 反连接      │ ▷      │ 只返回不能匹配的左表元组              │
├─────────────┼────────┼───────────────────────────────────────┤
│ 聚集        │ ℱ      │ COUNT, SUM, AVG, MAX, MIN             │
├─────────────┼────────┼───────────────────────────────────────┤
│ 分组        │ γ      │ GROUP BY + 聚集函数                   │
└─────────────┴────────┴───────────────────────────────────────┘

第五章 运算符优先级与表达式

理解运算符优先级和表达式构造规则,对于正确书写和阅读关系代数表达式至关重要。

5.1 运算符优先级

优先级规则

关系代数运算符的优先级从高到低:

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    运算符优先级(从高到低)                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  优先级 1(最高):                                             │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 括号 ()                                               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  优先级 2:                                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 一元运算符:σ(选择)、π(投影)、ρ(重命名)         │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  优先级 3:                                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 笛卡尔积 ×、各种连接 ⋈                                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  优先级 4(最低):                                             │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 集合运算:∪(并)、∩(交)、-(差)                   │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
优先级表
优先级 运算符 类型 结合性
1 () 括号 -
2 σ, π, ρ 一元 右结合
3 ×, ⋈, ÷ 二元 左结合
4 ∪, ∩, - 二元 左结合
优先级示例
复制代码
表达式:π_A(σ_B>5(R ⋈ S)) ∪ T

解析顺序:
1. R ⋈ S                    -- 先执行连接
2. σ_B>5(...)              -- 再执行选择
3. π_A(...)                -- 然后执行投影
4. ... ∪ T                 -- 最后执行并运算

等价于:(π_A(σ_B>5((R ⋈ S)))) ∪ T

5.2 关系代数表达式

表达式的构造规则

关系代数表达式由以下规则递归定义:

复制代码
基本表达式:
1. 关系名R是一个表达式(每个关系本身就是表达式)
2. 常量关系是一个表达式

归纳规则:
如果E₁和E₂是表达式,则以下也是表达式:
3. E₁ ∪ E₂       -- 并
4. E₁ - E₂       -- 差
5. E₁ × E₂       -- 笛卡尔积
6. σ_F(E₁)       -- 选择
7. π_A(E₁)       -- 投影
8. E₁ ⋈ E₂       -- 连接
9. ρ_X(E₁)       -- 重命名
表达式树

复杂的关系代数表达式可以用表达式树表示:

复制代码
查询:查询选修了数据库课程且成绩大于85分的学生姓名

π_Name(σ_Cname='数据库' ∧ Grade>85(Student ⋈ SC ⋈ Course))

表达式树:

                    π_Name
                       │
              σ_Cname='数据库' ∧ Grade>85
                       │
                      ⋈
                    /   \
                   ⋈     Course
                 /   \
            Student   SC

执行顺序(自底向上):
1. Student ⋈ SC
2. 结果 ⋈ Course
3. σ_Cname='数据库' ∧ Grade>85(结果)
4. π_Name(结果)

5.3 查询优化基础

数据库优化器使用关系代数的等价变换规则来优化查询。

等价变换规则
规则 表达式 说明
选择串联 σ_F1∧F2® = σ_F1(σ_F2®) 选择可拆分
选择交换 σ_F1(σ_F2®) = σ_F2(σ_F1®) 选择顺序可换
投影串联 π_A(π_B®) = π_A®,A⊆B 投影可合并
选择与投影 π_A(σ_F®) = σ_F(π_A®),F只涉及A 选择投影可换
选择与笛卡尔积 σ_F(R × S) = σ_F® × S,F只涉及R 选择下推
投影与笛卡尔积 π_{A∪B}(R × S) = π_A® × π_B(S) 投影下推
连接交换 R ⋈ S = S ⋈ R 连接可交换
连接结合 (R ⋈ S) ⋈ T = R ⋈ (S ⋈ T) 连接可结合
优化策略
复制代码
核心思想:尽早减少数据量

┌─────────────────────────────────────────────────────────────────┐
│                    查询优化基本策略                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  策略1:尽早执行选择(Selection Push-Down)                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 选择运算可以大幅减少元组数                            │   │
│  │ • 应尽可能将选择操作下推到表达式树的底部                │   │
│  │ • 例如:σ_F(R × S) → σ_F(R) × S(当F只涉及R)          │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  策略2:尽早执行投影(Projection Push-Down)                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 投影可以减少每个元组的宽度                            │   │
│  │ • 应尽可能将投影操作下推                                │   │
│  │ • 去除后续不需要的属性                                  │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  策略3:避免笛卡尔积                                            │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 笛卡尔积产生最大的结果集                              │   │
│  │ • 尽可能用连接代替笛卡尔积+选择                         │   │
│  │ • σ_F(R × S) → R ⋈_F S                                  │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  策略4:合并连续的选择和投影                                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 多个选择合并:σ_F1(σ_F2(R)) → σ_F1∧F2(R)              │   │
│  │ • 多个投影合并:π_A(π_B(R)) → π_A(R)                    │   │
│  │ • 减少中间结果的生成次数                                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
优化示例
复制代码
原始查询:
π_Name(σ_Cname='数据库' ∧ Grade>85(Student ⋈ SC ⋈ Course))

优化前的表达式树:
                    π_Name
                       │
              σ_Cname='数据库' ∧ Grade>85
                       │
                      ⋈
                    /   \
                   ⋈     Course
                 /   \
            Student   SC

优化后的表达式树(选择下推):
                    π_Name
                       │
                      ⋈
                    /   \
                   ⋈     σ_Cname='数据库'(Course)
                 /   \
            Student  σ_Grade>85(SC)

优化效果:
- 先过滤SC中成绩>85的记录
- 先过滤Course中数据库课程
- 再进行连接,中间结果更小

本章小结

复制代码
运算符优先级与表达式要点:

┌─────────────────────────────────────────────────────────────────┐
│                                                                 │
│  优先级:括号 > 一元(σ,π) > 连接(⋈,×) > 集合(∪,∩,-)           │
│                                                                 │
│  表达式树:从叶子向根执行                                       │
│                                                                 │
│  优化核心:                                                     │
│  1. 选择尽早执行(减少行数)                                    │
│  2. 投影尽早执行(减少列数)                                    │
│  3. 避免笛卡尔积                                                │
│  4. 合并连续操作                                                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

第六章 关系代数与SQL对照

关系代数是SQL的理论基础,理解两者的对应关系有助于深入理解数据库查询。

6.1 运算符对照表

完整对照表
关系代数 符号 SQL语法 示例
R ∪ S UNION SELECT * FROM R UNION SELECT * FROM S
R ∩ S INTERSECT SELECT * FROM R INTERSECT SELECT * FROM S
R - S EXCEPT / MINUS SELECT * FROM R EXCEPT SELECT * FROM S
笛卡尔积 R × S CROSS JOIN SELECT * FROM R CROSS JOIN S
选择 σ_F® WHERE SELECT * FROM R WHERE F
投影 π_A® SELECT A SELECT A FROM R
自然连接 R ⋈ S NATURAL JOIN SELECT * FROM R NATURAL JOIN S
θ连接 R ⋈_θ S JOIN ON SELECT * FROM R JOIN S ON θ
左外连接 R ⟕ S LEFT OUTER JOIN SELECT * FROM R LEFT JOIN S ON ...
右外连接 R ⟖ S RIGHT OUTER JOIN SELECT * FROM R RIGHT JOIN S ON ...
全外连接 R ⟗ S FULL OUTER JOIN SELECT * FROM R FULL JOIN S ON ...
聚集 ℱ® 聚集函数 SELECT COUNT(*), AVG(A) FROM R
分组 γ_A,F® GROUP BY SELECT A, F FROM R GROUP BY A
重命名 ρ_S® AS SELECT * FROM R AS S

6.2 SQL查询转换为关系代数

示例1:简单选择投影
sql 复制代码
SELECT Sno, Name 
FROM Student 
WHERE Age > 20;

转换为关系代数:

复制代码
π_Sno,Name(σ_Age>20(Student))
示例2:多表连接
sql 复制代码
SELECT Student.Sno, Name, Cno, Grade
FROM Student, SC
WHERE Student.Sno = SC.Sno AND Grade > 80;

转换为关系代数:

复制代码
π_Sno,Name,Cno,Grade(σ_Grade>80(Student ⋈ SC))
示例3:带聚集的分组查询
sql 复制代码
SELECT Sno, AVG(Grade) as AvgGrade
FROM SC
GROUP BY Sno
HAVING AVG(Grade) > 85;

转换为关系代数:

复制代码
σ_AvgGrade>85(γ_Sno,AVG(Grade)→AvgGrade(SC))

6.3 关系代数查询转换为SQL

示例1:选择+投影+连接
复制代码
关系代数:
π_Name(σ_Grade>90(Student ⋈ SC))

转换为SQL:

sql 复制代码
SELECT DISTINCT Name
FROM Student NATURAL JOIN SC
WHERE Grade > 90;
示例2:除法运算
复制代码
关系代数:
SC ÷ Course
(查询选修了所有课程的学生)

转换为SQL:

sql 复制代码
-- 方法1:双重NOT EXISTS
SELECT DISTINCT Sno
FROM SC AS SC1
WHERE NOT EXISTS (
    SELECT * FROM Course
    WHERE NOT EXISTS (
        SELECT * FROM SC AS SC2
        WHERE SC2.Sno = SC1.Sno AND SC2.Cno = Course.Cno
    )
);

-- 方法2:COUNT比较
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(DISTINCT Cno) = (SELECT COUNT(*) FROM Course);
示例3:差运算
复制代码
关系代数:
Student - π_Sno,Name,Age(Student ⋈ SC)
(查询没有选课的学生)

转换为SQL:

sql 复制代码
SELECT * FROM Student
WHERE Sno NOT IN (SELECT DISTINCT Sno FROM SC);

-- 或使用EXCEPT
SELECT * FROM Student
EXCEPT
SELECT Student.* FROM Student, SC WHERE Student.Sno = SC.Sno;

第七章 综合练习与案例

通过实际案例巩固关系代数的应用。

7.1 基础练习

使用以下关系进行练习:

复制代码
Student(Sno, Sname, Age, Sex, Dept)  -- 学生表
Course(Cno, Cname, Credit, Teacher)  -- 课程表
SC(Sno, Cno, Grade)                  -- 选课表
练习1:单表查询

Q1:查询计算机系年龄大于20岁的女生

复制代码
σ_Dept='计算机' ∧ Age>20 ∧ Sex='女'(Student)

Q2:查询所有学生的姓名和年龄

复制代码
π_Sname,Age(Student)

Q3:查询所有课程的课程名

复制代码
π_Cname(Course)
练习2:两表连接

Q4:查询选修了课程的学生姓名和成绩

复制代码
π_Sname,Grade(Student ⋈ SC)

Q5:查询成绩大于90分的学生姓名和课程名

复制代码
π_Sname,Cname(σ_Grade>90(Student ⋈ SC ⋈ Course))

7.2 综合案例

案例1:多表复杂查询

需求:查询选修了"数据库"课程且成绩高于张三的所有学生姓名

复制代码
分步求解:

Step 1:找出"数据库"课程号
π_Cno(σ_Cname='数据库'(Course)) → 假设结果为{C1}

Step 2:找出张三的数据库成绩
π_Grade(σ_Sname='张三'(Student) ⋈ σ_Cno='C1'(SC)) → 假设结果为{85}

Step 3:找出数据库成绩高于85的学生
π_Sname(σ_Grade>85(σ_Cno='C1'(SC) ⋈ Student))

完整表达式:
π_Sname(σ_Grade>(π_Grade(σ_Sname='张三'(Student) ⋈ σ_Cname='数据库'(Course) ⋈ SC))
        (Student ⋈ σ_Cname='数据库'(Course) ⋈ SC))
案例2:集合运算

需求:查询选修了C1或C2课程的学生学号

复制代码
π_Sno(σ_Cno='C1'(SC)) ∪ π_Sno(σ_Cno='C2'(SC))

需求:查询同时选修了C1和C2课程的学生学号

复制代码
π_Sno(σ_Cno='C1'(SC)) ∩ π_Sno(σ_Cno='C2'(SC))

需求:查询选修了C1但没选C2的学生学号

复制代码
π_Sno(σ_Cno='C1'(SC)) - π_Sno(σ_Cno='C2'(SC))

7.3 典型问题

问题1:"全部"类型查询(除法运算)

需求:查询选修了所有课程的学生学号

复制代码
解题关键:使用除法运算

SC ÷ π_Cno(Course)

验证:如果学生S1选了C1、C2、C3,S2只选了C1、C2
而所有课程是C1、C2、C3
则结果只有S1

需求:查询被所有学生都选修的课程

复制代码
先投影出学生-课程关系的转置视图:
SC' = π_Cno,Sno(SC)

SC' ÷ π_Sno(Student)
问题2:嵌套查询转换

SQL嵌套查询:

sql 复制代码
SELECT Sname FROM Student
WHERE Sno IN (
    SELECT Sno FROM SC WHERE Grade > 90
);

转换为关系代数:

复制代码
π_Sname(Student ⋈ π_Sno(σ_Grade>90(SC)))

或使用半连接:
π_Sname(Student ⋉ σ_Grade>90(SC))

第八章 面试与考试重点

8.1 高频考点

考点1:五种基本运算

必须记住的五种基本运算:

运算 符号 记忆要点
合并两个兼容关系
- 从R中减去S
笛卡尔积 × 所有组合
选择 σ 选行(水平切分)
投影 π 选列(垂直切分)

为什么这五个是基本的?

  • 交运算可表示为:R ∩ S = R - (R - S)
  • 连接运算可表示为:R ⋈ S = σ_条件(R × S)
  • 除法运算可表示为:R ÷ S = π_X® - π_X((π_X® × S) - R)
考点2:关系代数表达式书写

常见题型:

  1. 给定需求,写出关系代数表达式
  2. 给定SQL,转换为关系代数
  3. 给定表达式,解释其含义

书写技巧:

复制代码
1. 确定输出属性 → 投影
2. 确定过滤条件 → 选择
3. 确定需要哪些表 → 连接
4. 处理"全部"类型 → 除法
考点3:选择与投影的区别
比较项 选择(σ) 投影(π)
作用 选择行 选择列
切分方向 水平 垂直
结果元组数 ≤原关系 ≤原关系(去重)
结果属性数 =原关系 ≤原关系
去重 不去重 自动去重

8.2 常见面试题

Q1:解释自然连接与等值连接的区别
复制代码
答案要点:

1. 等值连接:
   - 需要显式指定连接条件(A=B)
   - 结果中保留两个连接属性列
   - R ⋈_{R.B=S.B} S

2. 自然连接:
   - 自动在同名属性上进行等值连接
   - 结果中同名属性只保留一列
   - R ⋈ S

3. 关系:
   自然连接 = 等值连接 + 投影去除重复列
Q2:除法运算的应用场景
复制代码
答案要点:

适用场景:包含"所有"、"全部"、"每一个"等关键词的查询

典型例子:
- 查询选修了所有课程的学生
- 查询被所有顾客购买过的商品
- 查询访问了所有页面的用户

公式:R ÷ S
- R必须包含S的所有属性
- 结果是R中与S完全匹配的元组在非公共属性上的投影
Q3:关系代数与SQL的对应关系
复制代码
答案要点:

| 关系代数 | SQL组成部分 |
|----------|------------|
| π(投影)| SELECT子句 |
| σ(选择)| WHERE子句  |
| ⋈(连接)| JOIN子句   |
| ∪(并)  | UNION      |
| γ(分组)| GROUP BY   |
| ℱ(聚集)| COUNT/SUM/AVG等 |

8.3 真题解析

软考真题1

题目: 设有关系R(A,B,C)和S(C,D),写出下列查询的关系代数表达式:

查询R和S在属性C上做自然连接后,B>5的元组的A值。

答案:

复制代码
π_A(σ_B>5(R ⋈ S))

解析:

  1. R ⋈ S:自然连接(在C上)
  2. σ_B>5(...):选择B>5的元组
  3. π_A(...):投影出A属性
软考真题2

题目: 关系R和S如下图所示,计算R ÷ S的结果。

复制代码
R:                    S:
┌───┬───┐            ┌───┐
│ A │ B │            │ B │
├───┼───┤            ├───┤
│ 1 │ a │            │ a │
│ 1 │ b │            │ b │
│ 1 │ c │            │ c │
│ 2 │ a │            └───┘
│ 2 │ b │
│ 3 │ a │
└───┴───┘

答案:

复制代码
结果:
┌───┐
│ A │
├───┤
│ 1 │
└───┘

解析:
- A=1对应的B值:{a,b,c} ⊇ S中的{a,b,c} ✓
- A=2对应的B值:{a,b} ⊉ S中的{a,b,c} ✗
- A=3对应的B值:{a} ⊉ S中的{a,b,c} ✗
所以只有A=1满足条件

附录

附录A:关系代数符号速查表

运算 符号 读法 运算类型 LaTeX
Union 集合运算 \cup
Intersection 集合运算 \cap
- Difference 集合运算 -
笛卡尔积 × Cross Product 集合运算 \times
选择 σ Sigma (Select) 专门运算 \sigma
投影 π Pi (Project) 专门运算 \pi
连接 Bowtie (Join) 专门运算 \bowtie
÷ Division 专门运算 \div
左外连接 Left Outer Join 扩展运算 \leftouterjoin
右外连接 Right Outer Join 扩展运算 \rightouterjoin
全外连接 Full Outer Join 扩展运算 \fullouterjoin
半连接 Semi Join 扩展运算 \ltimes
反连接 Anti Join 扩展运算 \rhd
聚集 ℱ 或 G Aggregation 扩展运算 \mathcal{F}
分组 γ Gamma (Group) 扩展运算 \gamma
重命名 ρ Rho (Rename) 扩展运算 \rho

附录B:五种基本运算详解

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    五种基本运算                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. 并(∪)                                                     │
│     R ∪ S = { t | t ∈ R ∨ t ∈ S }                               │
│     合并两个关系,去重                                          │
│                                                                 │
│  2. 差(-)                                                     │
│     R - S = { t | t ∈ R ∧ t ∉ S }                               │
│     R中有但S中没有的                                            │
│                                                                 │
│  3. 笛卡尔积(×)                                               │
│     R × S = { t₁t₂ | t₁ ∈ R ∧ t₂ ∈ S }                          │
│     所有可能的组合                                              │
│                                                                 │
│  4. 选择(σ)                                                   │
│     σ_F(R) = { t | t ∈ R ∧ F(t) = true }                        │
│     按条件选择行                                                │
│                                                                 │
│  5. 投影(π)                                                   │
│     π_A(R) = { t[A] | t ∈ R }                                   │
│     选择列并去重                                                │
│                                                                 │
│  其他运算都可以用这五种表示:                                   │
│  • R ∩ S = R - (R - S)                                          │
│  • R ⋈ S = π_去重(σ_条件(R × S))                                │
│  • R ÷ S = π_X(R) - π_X((π_X(R) × S) - R)                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

附录C:参考资料

经典教材:

  • 《数据库系统概念》(Database System Concepts)- Silberschatz等
  • 《数据库系统原理》- 王珊、萨师煊
  • 《数据库原理及应用》- 严蔚敏

在线资源:

工具推荐:


本文档详细介绍了关系代数的基本运算,包括并、交、差、笛卡尔积(传统集合运算)和选择、投影、连接、除法(专门关系运算),以及扩展运算、运算符优先级、SQL对照、综合练习和面试重点。适合作为数据库原理学习和面试复习的参考资料。

相关推荐
历程里程碑2 小时前
Linux 16 环境变量
linux·运维·服务器·开发语言·数据库·c++·笔记
流㶡2 小时前
mysql学习笔记之创建表、导入导出数据
数据库·mysql
Monkey的自我迭代2 小时前
实战项目数据桥agent复盘
数据库·python·oracle
赵锦川2 小时前
Oracle数据库序列的创建
数据库
柱子jason3 小时前
使用IOT-Tree对接工业现场PLC并把采集数据记录到关系数据库中
数据库·物联网·plc·工业物联网·工业自动化·iot-tree·生产线配套
2301_822375443 小时前
Python虚拟环境(venv)完全指南:隔离项目依赖
jvm·数据库·python
2301_790300963 小时前
Python类型提示(Type Hints)详解
jvm·数据库·python
一路向北⁢3 小时前
Spring Boot 3 整合 SSE (Server-Sent Events) 企业级最佳实践(二)
java·数据库·spring boot·sse·通信
远方16093 小时前
112-Oracle database 26ai下载和安装环境准备
大数据·数据库·sql·oracle·database