数据库关系代数(Mysql)
下面用最经典的学生-课程数据库,把关系代数所有常用运算一次性讲全,
每条都配:含义 + 语法 + MySQL 对照 SQL + 例子结果说明。
0. 示例表结构(全程用这 3 张表)
1)学生表 Student
S(Sno, Sname, Sage, Ssex, Sdept)
- Sno:学号
- Sname:姓名
- Sage:年龄
- Ssex:性别
- Sdept:所在系
2)课程表 Course
C(Cno, Cname, Credit, Tno)
- Cno:课号
- Cname:课程名
- Credit:学分
- Tno:教师号
3)选课表 SC
SC(Sno, Cno, Grade)
- Sno:学号
- Cno:课号
- Grade:成绩
1. 传统集合运算
1.1 并(Union)∪
含义:两个同结构关系的所有元组,去重合并。
关系代数:
R ∪ S
MySQL:
SELECT * FROM R
UNION
SELECT * FROM S;
例子:
查询计算机系 或 数学系的所有学生。
σ[Sdept='CS'(S)] ∪ σ[Sdept='MA'(S)]
1.2 交(Intersection)∩
含义:同时出现在 R 和 S 中的元组。
关系代数:
R ∩ S
MySQL:
SELECT * FROM R
INTERSECT
SELECT * FROM S;
例子:
查询既选了 1 号课,又选了 2 号课的学生学号。
π[Sno(σ[Cno=1(SC])] ∩ π[Sno(σ[Cno=2(SC])]
1.3 差(Difference)−
含义:在 R 中但不在 S 中的元组。
关系代数:
R − S
MySQL:
SELECT * FROM R
EXCEPT
SELECT * FROM S;
例子:
查询选了课但没选 1 号课的学生。
π[Sno(SC)] − π[Sno(σ[Cno=1(SC])]
2. 专门关系运算(核心)
2.1 选择 σ(Selection)
行过滤:满足条件的元组。
语法:
σ[条件](关系)
例子 1:查询计算机系学生
σ[Sdept='CS'(S)]
SQL:
SELECT * FROM Student WHERE Sdept = 'CS';
例子 2:成绩 ≥ 90
σ[Grade>=90(SC)]
2.2 投影 π(Projection)
列过滤:保留某些属性,去掉重复行。
语法:
π[属性列表](关系)
例子:查询所有学生的姓名和所在系
π[Sname,Sdept(S)]
SQL:
SELECT DISTINCT Sname, Sdept FROM Student;
2.3 笛卡尔积 ×(Cartesian Product)
所有元组两两组合,不加条件。
语法:
R × S
SQL:
SELECT * FROM R, S;
-- 或
SELECT * FROM R CROSS JOIN S;
例子:学生 × 课程
S × C
2.4 自然连接 ⋈(Natural Join)
自动按同名属性等值连接,去重公共列。
语法:
R ⋈ S
SQL:
SELECT * FROM R NATURAL JOIN S;
经典例子:查询学生及其选课成绩
S ⋈ SC
2.5 条件连接(θ-连接)⋈[条件]
笛卡尔积 + 选择,等价于内连接。
语法:
R ⋈[条件] S
等价:
σ[条件](R × S)
SQL:
SELECT * FROM R JOIN S ON 条件;
例子:学生与选课按学号连接
S ⋈[S.Sno=SC.Sno] SC
2.6 左外连接 / 右外连接 / 全外连接
左外连接 ⋊=(Left Outer Join)
左边全部保留,右边匹配不上填 NULL。
关系代数:
S ⋊= SC
SQL:
SELECT * FROM S LEFT JOIN SC ON S.Sno=SC.Sno;
用途:查所有学生,包括没选课的。
3. 高级运算(考试/工程高频)
3.1 除运算 ÷(Division)
“包含全部”类查询:包含 S 中所有相关元组的 R 元组。
语法:
R ÷ S
经典例子:
查询选了所有课程的学生学号。
π[Sno,Cno(SC)] ÷ π[Cno(C)]
SQL 思路(分组+计数):
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(DISTINCT Cno) = (SELECT COUNT(*) FROM C);
3.2 更名运算 ρ(Rename)
修改关系名/属性名,解决重名冲突。
语法:
ρ[新关系名(新属性1,新属性2...)(R)]
例子:把 SC 改名为 SC_NEW(S#, C#, G)
ρ[SC_NEW(S#,C#,G)(SC)]
SQL:
SELECT Sno AS S#, Cno AS C#, Grade AS G FROM SC AS SC_NEW;
4. 组合查询大全(考试必背)
例 1:查询选了“数据库”的学生姓名
π[Sname( σ[Cname='数据库'(C ⋈ SC ⋈ S) ]]
SQL:
SELECT DISTINCT Sname
FROM Student
JOIN SC ON Student.Sno=SC.Sno
JOIN Course ON SC.Cno=Course.Cno
WHERE Cname='数据库';
例 2:查询没选 1 号课的学生
π[Sno(S)] − π[Sno( σ[Cno=1(SC]) ]
例 3:查询至少选了 2 门课的学生
π[Sno( σ[COUNT(*)>=2( γ[Sno;COUNT(*)(SC]) ]]
(带分组扩展 γ)
SQL:
SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*)>=2;
例 4:查询成绩为空的学生(没成绩)
π[Sname(S ⋊= σ[Grade IS NULL(SC]) ]
例 5:查询年龄大于 20 岁的女生
σ[Sage>20 ∧ Ssex='女'(S)]
5. 关系代数 ↔ SQL 速记表
| 关系代数 | SQL 对应 | 作用 |
|---|---|---|
| σ条件 | WHERE 条件 | 选行 |
| πA,B | SELECT A,B | 选列 |
| R × S | CROSS JOIN | 笛卡尔积 |
| R ⋈ S | NATURAL JOIN | 自然连接 |
| R ⋈[c] S | JOIN ON c | 条件连接 |
| R ⋊= S | LEFT JOIN | 左外连接 |
| R ∪ S | UNION | 并 |
| R ∩ S | INTERSECT | 交 |
| R − S | EXCEPT | 差 |
| R ÷ S | GROUP BY+HAVING | 包含全部 |
| ρ | AS | 更名 |