最近学数据库概论学到了
关系数据库
的关系代数了。哎嘛,真的把我整晕了,尤其是关系代数的使用,很容易让人被蒙在鼓里。
对我来说
槽点最大的莫过于书上的例子不多了,本来就挺抽象的一种
查询
语言,加上没有足够多让我懂的例子
(不过我本来也比较迟钝了)
,真的是难上加难...
但没办法啊,这是我需要跨过的一道坎,于是我决定慢慢写出这篇小记(
主要针对数据库关系代数
)。不求挖的多深,但求能理解地透彻点😂
目标是...希望这篇文章对大家有所帮助吧!废话不多说,开整! 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 小概念
使用的表格: