# DBMS 关系代数

> 原文： [https://beginnersbook.com/2019/02/dbms-relational-algebra/](https://beginnersbook.com/2019/02/dbms-relational-algebra/)

在本教程中，我们将讨论**关系代数**。在前面的教程中，我们简要讨论了[关系代数和微积分](https://beginnersbook.com/2019/02/introduction-to-relational-algebra-calculus/)的基础知识，其中我们了解了使用这些理论数学系统的必要性。

## 什么是 DBMS 中的关系代数？

关系代数是一种**过程**查询语言，适用于关系模型。查询语言的目的是从数据库中检索数据或对数据执行各种操作，如插入，更新，删除。当我说关系代数是一种过程查询语言时，它意味着它告诉我们要检索哪些数据以及如何检索它们。

另一方面，关系演算是一种非过程式查询语言，这意味着它会告诉要检索哪些数据但不会告诉如何检索它。我们将在单独的教程中讨论关系演算。

## 关系代数中的运算类型

我们将这些操作分为两类：

1. 基本操作
2. 派生操作

### 基本/基本操作：

1. 选择（`σ`）
2. 投影（`Π`）
3. 并集（`∪`）
4. 差集（`-`）
5. 笛卡尔积（`X`）
6. 重命名（`ρ`）

### 衍生操作：

1. 自然连接（`⋈`）
2. 左，右，全外连接（`⟕`，`⟖`，`⟗`）
3. 交集（`∩`）
4. 除法（`÷`）

让我们在示例的帮助下逐一讨论这些操作。

## 选择运算符（`σ`）

选择运算符由 sigma（`σ`）表示，它用于查找满足给定条件的关系（或表）中的元组（或行）。

如果您了解一点 SQL，那么您可以将其视为 SQL 中的[`where`子句](https://beginnersbook.com/2014/05/where-clause-in-sql/)，它用于相同的目的。

**选择运算符语法（`σ`）**

```
σ Condition/Predicate(Relation/Table name)
```

### 选择运算符（`σ`）示例

```
Table: CUSTOMER
---------------

Customer_Id     Customer_Name      Customer_City
-----------     -------------      -------------
C10100           Steve              Agra
C10111           Raghu              Agra
C10115           Chaitanya          Noida
C10117           Ajeet              Delhi
C10118           Carl               Delhi

```

**查询：**

```
σ Customer_City="Agra" (CUSTOMER)  

```

**输出：**

```
Customer_Id   Customer_Name    Customer_City
-----------   -------------    -------------
C10100        Steve            Agra
C10111        Raghu            Agra
```

## 投影运算符（`Π`）

投影运算符由`Π`符号表示，用于从表（或关系）中选择所需的列（或属性）。

关系代数中的投影运算符类似于 SQL 中的[`Select`语句](https://beginnersbook.com/2018/11/sql-select/)。

**投影运算符语法（`Π`）**

```
∏ column_name1, column_name2, ...., column_nameN(table_name)
```

### 投影运算符（`Π`）示例

在这个例子中，我们有一个包含三列的表`CUSTOMER`，我们只想获取表的两列，我们可以在投影运算符`Π`的帮助下完成。

```
Table: CUSTOMER

Customer_Id     Customer_Name      Customer_City
-----------     -------------      -------------
C10100           Steve              Agra
C10111           Raghu              Agra
C10115           Chaitanya          Noida
C10117           Ajeet              Delhi
C10118           Carl               Delhi

```

**查询：**

```
∏ Customer_Name, Customer_City (CUSTOMER)  

```

**输出：**

```
Customer_Name      Customer_City
-------------      -------------
Steve              Agra
Raghu              Agra
Chaitanya          Noida
Ajeet              Delhi
Carl               Delhi
```

## 并集运算符（`∪`）

并集运算符用`∪`符号表示，用于从两个表（关系）中选择所有行（元组）。

让我们再讨论一下并集运算符。假设我们有两个关系`R1`和`R2`都有相同的列，我们想从这些关系中选择所有元组（行），然后我们可以在这些关系上应用并集运算符。

**注意：**两个表中存在的行（元组）只在并集中出现一次。简而言之，您可以说并集操作后没有重复项。

**并集运算符的语法（`∪`）**

```
table_name1 ∪ table_name2
```

### 并集运算符（`∪`）示例

表 1：`Course`

```
Course_Id  Student_Name   Student_Id
---------  ------------   ----------
C101        Aditya         S901
C104        Aditya         S901
C106        Steve          S911
C109        Paul           S921
C115        Lucy           S931

```

表 2：`Student`

```
Student_Id     Student_Name   Student_Age
------------   ----------     -----------
S901           Aditya         19
S911           Steve          18
S921           Paul           19
S931           Lucy           17
S941           Carl           16
S951           Rick           18
```

**查询：**

```
∏ Student_Name (COURSE) ∪ ∏ Student_Name (STUDENT)
```

**输出：**

```
Student_Name
------------
Aditya
Carl
Paul
Lucy
Rick
Steve

```

**注意：**正如你所看到的那样，输出中没有重复的名称，即使我们在两个表中都有很少的共同名称，同样在`COURSE`表中我们也有重复的名称。

## 交集运算符（`∩`）

交集运算符用`∩`符号表示，用于从两个表（关系）中选择公共行（元组）。

假设我们有两个关系`R1`和`R2`都有相同的列，我们想要选择两个关系中存在的所有元组（行），那么在这种情况下我们可以对这两个关系`R1∩R2`应用交集运算。

**注意：**只有那两个表中存在的那些行才会出现在结果集中。

**交集运算符语法（`∩`）**

```
table_name1 ∩ table_name2
```

### 交集运算符（`∩`）示例

让我们采取与上面相同的例子。

表 1：`Course`

```
Course_Id  Student_Name   Student_Id
---------  ------------   ----------
C101        Aditya         S901
C104        Aditya         S901
C106        Steve          S911
C109        Paul           S921
C115        Lucy           S931

```

表 2：`STUDENT`

```
Student_Id     Student_Name   Student_Age
------------   ----------     -----------
S901           Aditya         19
S911           Steve          18
S921           Paul           19
S931           Lucy           17
S941           Carl           16
S951           Rick           18
```

**查询：**

```
∏ Student_Name (COURSE) ∩ ∏ Student_Name (STUDENT)
```

**输出：**

```
Student_Name
------------
Aditya
Steve
Paul
Lucy

```

## 差集运算符（`-`）

差集运算符用`-`符号表示。假设我们有两个关系`R1`和`R2`，我们想要选择所有那些存在于关系`R1`中但不存在于关系`R2`中的元组（行），这可以使用集合差`R1-R2`来完成。

**差集运算符语法（`-`）**

```
table_name1 - table_name2
```

### 差集运算符（`-`）示例

让我们看看上面我们看到的课程和学生。

**查询：**

让我们编写一个查询来选择`STUDENT`表中但不存在于`COURSE`表中的学生姓名。

```
∏ Student_Name (STUDENT) - ∏ Student_Name (COURSE)
```

**输出：**

```
Student_Name
------------
Carl
Rick

```

## 笛卡尔积（`X`）

笛卡尔积用`X`符号表示。假设我们有两个关系`R1`和`R2`，然后这两个关系的笛卡尔积（`R1 X R2`）将第一关系`R1`的每个元组与第二关系`R2`的每个元组组合。我知道这听起来令人困惑，但是一旦我们举一个这样的例子，你就能理解这一点。

**笛卡尔积（`X`）**的语法

```
R1 X R2
```

### 笛卡尔积（`X`）示例

表 1：`R`

```
Col_A    Col_B
-----    ------
AA        100
BB        200
CC        300      

```

表 2：`S`

```
Col_X     Col_Y
-----     -----
XX         99
YY         11
ZZ         101

```

**查询：**

让我们查找表`R`和`S`的笛卡尔积。

```
R X S

```

**输出：**

```
Col_A    Col_B     Col_X     Col_Y
-----    ------    ------    ------
AA        100      XX         99
AA        100      YY         11
AA        100      ZZ         101
BB        200      XX         99
BB        200      YY         11
BB        200      ZZ         101
CC        300      XX         99
CC        300      YY         11
CC        300      ZZ         101

```

**注意：**输出中的行数始终是每个表中行数的乘积。在我们的示例中，表 1 有 3 行，表 2 有 3 行，因此输出有`3×3 = 9`行。

## 重命名（`ρ`）

重命名（`ρ`）操作可用于重命名关系的属性。

**重命名（`ρ`）语法：**

```
ρ(new_relation_name, old_relation_name)
```

### 重命名（`ρ`）示例

假设我们有一个表`Customer`，我们正在获取客户名称，我们将所得关系重命名为`CUST_NAMES`。

表：客户

```
Customer_Id     Customer_Name      Customer_City
-----------     -------------      -------------
C10100           Steve              Agra
C10111           Raghu              Agra
C10115           Chaitanya          Noida
C10117           Ajeet              Delhi
C10118           Carl               Delhi

```

**查询：**

```
ρ(CUST_NAMES, ∏(Customer_Name)(CUSTOMER))
```

**输出：**

```
CUST_NAMES
----------
Steve
Raghu
Chaitanya
Ajeet
Carl

```