最近学数据库概论学到了 关系数据库 的关系代数了。哎嘛,真的把我整晕了,尤其是关系代数的使用,很容易让人被蒙在鼓里。

对我来说 槽点最大的莫过于书上的例子不多了,本来就挺抽象的一种 查询 语言,加上没有足够多让我懂的例子 (不过我本来也比较迟钝了) ,真的是难上加难...
但没办法啊,这是我需要跨过的一道坎,于是我决定慢慢写出这篇小记( 主要针对数据库关系代数 )。不求挖的多深,但求能理解地透彻点😂
目标是...希望这篇文章对大家有所帮助吧!废话不多说,开整! o( ̄ヘ ̄o#)

注意,因采用了动图(WebP)直观表达,流量用户请慎重浏览~

关系代数是一种查询语言。

0x00 关系代数演示工具

仍在开发中,稍后会在这里放出在线网站链接~

你可以强势围观,这是一个开源的项目: https://github.com/SomeBottle/RA

咱有时间就会写写,不会咕咕咕哒! (。﹏。*)

0x01 小概念

展开阅读:行与列 , 目&度&元数 , 属性&字段 , 元组&基数&分量 , 域

& & 元数

1.如果使用关系表进行展示的话, 属性数(字段数) 其实就是 列数 ,而进一步我们将属性数称为 元数 或者 或者

2.这样看来其实 元数就是目,目也就是度

属性 & 字段

1. 属性 就是 字段 (至少在数据库关系表这里是这样),都表示的是

2.上面和下面的图中第一行 学号,姓名,性别... 等等是 属性名(字段名)

元组 & 基数 & 分量

1.表中的 一行 ,是 一条记录 ,也是 一个元组 ,有n个元素的元组可以被称为 n元组

2.记录(元组)的数称为 基数 ,一定一定注意辨别这里的基数和下面 域的基数

3. 分量 是元组中一个 属性对应的值

1. 就是属性的 取值范围所在

2.域是一个 集合 ,域这个 集合 里的值都是 统一数据类型的

3.域也有一个 域的基数 域的基数 代表域能取的值的数量,比如: 年龄属性的域={17,18,19,20,21,22,23,24,25} ,那么这个域的基数就是9

咱实话实说,关系代数这一部分第一个让我晕头的地方就是这个笛卡尔积o(≧口≦)o,接下来我尽力搞懂并用动图展示出来笛卡尔积到底做了什么。

为什么这里是 广义笛卡尔积 呢?我们先看 笛卡尔积 算了什么:

笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尔积(Cartesian product),又称直积,表示为X×Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员

摘自某百科

这个概念看得我脑袋嗡嗡的,什么叫 “第二个对象是Y的所有可能有序对的其中一个成员” ?结合例子琢磨了一会儿,我结合离散数学教材关于笛卡尔积的定义梳理了一下:

笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尔积,又称直积,表示为X×Y。X中的元素作为第一个元素,Y中的元素作为第二个元素,构成有序对。而笛卡尔积就是所有这样的有序对构成的一个集合。

接下来我们回到这里, 其实就是一个 集合 ,结合上文, 笛卡尔积是在域上面的一种<集合>运算 ,下面放个简单的例子:

复习一下,一个 允许的 不同取值的个数 称为这个 域的基数 。换种说法,也是一个 集合 中的 元素个数

在上图的示例中,TEACHER域里有 张前程,赵向前 两位老师,这个域的基数也就是2;而MAJOR域里有 计算机专业,信息专业 两个专业,这个域的基数也是2。最后算出的域中有四个有序对,结果这个域的基数是4.

域的基数为m和n 的两个域进行笛卡尔积后我们得到的 域的基数 就是 m×n (这里×是乘号的意思哈,不要多想! ( ̄△ ̄;))

仔细看一下能发现上面的例子中有个 有序对 的概念,不用怕,在关系这里我们后面就用不着它了!看看接下来这个例子:

到底其实我们算出了一个包含 老师所带专业课程的所有可能性 的集合(域),把每一项元素放进关系中,这不就是元组嘛!

现在再说回 广义笛卡尔积 ,为什么“广义”呢?因为它面向的是关系,通过 操作元组 进行运算。接下来我们快速上一个例子:

两个分别为 n目 m目 的关系R和S的广义笛卡尔积是一个 (n+m)列(目) 的元组的集合(新关系)。元组的 前n列 关系R 的一个元组, 后m列 关系S 的一个元组。若R有k1个元组,S有k2个元组,则关系R和关系S的广义笛卡尔积有 k1 × k2 个元组。

进行广义笛卡尔积时对两个关系的要求是比较宽松的:

不要求 两个关系的 目(度,元数,属性数,列数) 相同。

有了上面这条,其实也应该知道了,广义笛卡尔积也 不要求 相应属性取自同一个域。

在这之后我们再来个详细点的例子,把两张 不同 的表进行笛卡尔积:

在数据库关系里, 笛卡尔积 是面向 域(集合) ,操作元素来进行计算的;而 广义笛卡尔积 是面向 关系 ,操作元组来进行计算的。

随便两个关系 都可以进行广义笛卡尔积运算(在保证 结果的关系 有意义的情况下)

逻辑表达式形如 A θ B ,也就是 将A表达式和B表达式进行比较 θ 是比较运算符。举几个例子: StudentAge > 17 , 17 < StudentAge , CourseNum ≥ StudentNum , StudentName = 'Jerry'

上面的例子中 StudentAge , StudentName 一类是属性名,而 17 , 'Jerry' 一类则是常量。

字符串常量 请一定记得用 单引号 括起来。

所以A和B表达式可以是 属性名 , 常量 , 书上还补充说可以是 简单函数 ,不过在基础应用中不太能见得到。

多个 逻辑表达式可以用 逻辑运算符 进行连接,举几个例子: AθB ∧ CθD , AθB ∨ CθD , ┐(AθB)

大体来说, 选择 选的是关系中符合条件的 元组 ,得到的结果是 元组集合(也算一个关系)

投影可以说是四种专门关系运算中最简单的一种了,我们可以简单走一遍~

投影是对 和少部分 进行操作的一种运算,我们先直接上例子:

投影语句形如 ΠA(关系) 其中 A 是属性名。

投影选出了 特定属性名 对应的

投影选择出 一列或多列 属性列后,需要 去除重复元组 , 这也是为什么说投影涉及少部分行上的操作。

除运算是同时从 的方向进行运算的。

这里的除运算理解起来可能有点“绕”,尤其是书上还引用了一个 “象集” 的概念来定义除法。那好吧 o(* ̄3 ̄)o,我们先看看 象集做了啥子

象集这个概念以我的水平实在是难以用文字表达清楚,这里就先上直观示例了:

上面的例子R(X,Z)中X指代了 单个属性列B ,接下来我们来几张静态图展示一下 X代表一个属性组的情况 (其实是这里懒得做动图了_(´ཀ`」 ∠)_)

【展开查看例子】 X代表包含B,C属性列的属性组

象集做的事无非是 一次选择 一次投影 。比如我想找R关系中 x的象集 ,那么先选择的是 X的分量 等于 x 的 元组(可能有多个,组成集合) ,然后将这些元组(集)在 Z属性组 上进行投影,得到x的象集。

象集的英文是Image Set ,没错,它也是 集合 !如果最后得到的结果中有重复项请记得 去掉重复项

接下来继续看 除运算 ,书上之所以用了象集的概念来定义,我觉得是因为除运算实际上是 求象集的 “反向操作” ,从结果找源头 ,看接下来这个例子:

上面这个例子中结果得到的是 单属性列A ,下面我们再来个相除得到 属性组 的例子:

总结一下就是:

这里的 除运算 可以看作是 求象集的反向操作 。比如我算 R ÷ S ,其实就是找 S关系和R关系相同的部分 R中谁的象集

通过上面两个例子可以发现,除号 前面 关系的 元组数 一定 除号 后面 关系的 元组数 。例如我算 R÷S ,如果R的元组数<S的元组数,是肯定 除了个寂寞的

另外,进行除运算的两个关系必须要有 共同的属性列 , 不然运算是没有任何效果的。

连接的符号是 ,一般连接是对 进行操作,一部分情况( 自然连接 )下连接 还要 进行(去重)操作。

连接因为条件不同,被分为了 θ连接 等值连接 自然连接 几种,咱也准备分开记这几个了~

连接必需的一步

连接其实等同于从两个关系的 广义笛卡尔积 中按 条件 进行 选择 ,运算式中⋈符号下面的表达式其实和选择里的F一样是 逻辑表达式 ,但 要注意 ,这里逻辑表达式θ两端用于比较的属性组是有限制的, 详细看下面的θ连接

例子中得到的R和S两个关系的广义笛卡尔积:

R.COURSEID S.COURSEID TEACHER

其中属性列 ID , NAME , R.COURSEID 是原关系R的属性列,而 S.COURSEID TEACHER 是原关系S的属性列

在接下来的示例中,咱就用这张表来做示例了嗷~(/▽\)

θ连接其实简称就是连接,很有存在感的便是 代表比较运算符的 θ 了 ( ̄□ ̄;)
废话不多说,我们先上直观例子:

主要操作就是从两个关系的广义笛卡尔积中 按条件进行选择 了,由此很大程度上可以参考上面的 选择 部分。尽管如此,还是要 注意 这些限定:

R ⋈ S(逻辑表达式:A θ B) 进行举例, A属性组 只能在 R 这部分选,而 B属性组 只能在 S 这部分选。

A B 是属性组,那么A和B的 度数(列数) 一定要 相同

上面举的例子可能还有点不清不白,其实咱还可以皮点嘛( ̄^ ̄)ゞ,比如说这样写:

在逻辑表达式中我们将学号 ID 和课程号 S.COURSEID 相比。可想而知,因为 在广义笛卡尔积结果中 学号是 恒大于 课程号的,所以结果自然是:

等值连接是基于 θ连接 的,不同的是等值连接规定 θ是等号= ,话不多说,直接上例子:

关系R与关系S自然连接表示为: R ⋈ S

自然连接是在 等值连接 上的扩充,不过自然连接有了新的要求:

逻辑表达式中进行比较的两个属性组 A B 必须是 相同的属性组

自然连接结果中要 去除重复的属性列

结合上面两点,自然连接 过程中一定 会有 重复列 出现。

第1点 来说,比如上面的例子中, R.COURSEID 是R关系中的 COURSEID 属性列,而 S.COURSEID 是S关系中的 COURSEID 属性列,他们都是 COURSEID 属性,都是 课程号 ,所以可以进行自然连接。

如果我拿R关系中的 ID 和S关系中的 COURSEID 属性列作为比较对象,因为二者并不是同一个属性名, 无法进行自然连接

第2点 的话咱还是整个例子(紧接上一个等值连接的例子,因为等值连接举的例子中R关系的COURSEID和S关系的COURSEID是同一个属性):

外连接则又是在 自然连接 上的扩展(一环套一环啊喂(°ー°〃) ),它与自然连接不同的地方是 保留了悬浮元组

什么是 悬浮元组

在进行自然连接后,原 R关系 S关系 中因为 不满足条件 ,可能有 元组 没有在 连接结果中出现,也就是在连接过程中被 抛弃了 ,这些被抛弃的元组就是 悬浮元组 。(顺便学个新的英语单词: dangle[verb.]悬挂,悬垂

上面的例子中的悬浮元组是:

COURSEID

0x04 After all

这篇文章写出来一方面是当作我自己学习的笔记,将来如果我忘记了(这个将来可能离现在不远了,我记性很差TAT)能随时捡起来,所以 在我的角度 上尽可能地表达详细了;另一方面也是希望 能多多少少帮助 到大家,毕竟现在关于关系代数的知识在网上还是有点分散的。

因为这篇文章写了两周,中间可能因为时间间断导致我突然想不起来之前 想写什么 了,可能有遗漏或者写错的地方,也请各位多加指教。

写完后咱觉得动图播放速度可能还是有点快了,于是有了写个 关系代数演示小工具 的想法,稍后将作为上方的 0x00环节 放出,目标是能让看到该文章的各位(包括我自己)在动手中加深理解。

0x01 小概念 使用的表格: