數據庫的類型
我們一般會把數據庫簡單區分成關係型數據庫(SQL)和非關係型數據庫(NoSQL)。
關係型數據庫:MySQL、MariaDB、PostgreSQL、Oracle、SQL Server。比較有意思的是關係型數據庫的logo很多都是動物。
非關係型數據庫:一般只需要知道兩個——Redis和MongoDB。Redis是鍵值類型(Key-Value)的數據庫,類似JAVA裏的Collection類的Map,默認情況下Redis很難進行類似SQL裏的
where
和級聯select
操作;MongoDB被稱作文檔型數據庫,介於SQL和Redis之間,它沒有表(Table)的結構,你想怎麼插入就怎麼插入,但是可以進行級聯條件查詢等操作。
關係型數據庫的關係
記爲關係模式,其中爲關係名,等爲組成該關係的屬性名集合。
關係模式的詳細表示爲——即爲;爲中屬性來自的域;爲屬性向域的映射集合;爲依賴關係,如主鍵、外鍵等。但根據考試經驗,這玩意一般用不到。
可以簡單把理解成一個表,等爲屬性列的名字。如一個學生信息表:學生信息表(學號,性別,生日,專業,姓名...)
。這樣的理解方式有助於後面對連接操作的理解。
表裏的每個值被稱爲元組,即所謂的“行”。
關係代數
關係代數是關係型數據庫所完備的一類數學邏輯。其基本運算符有:
集合/邏輯運算符 | 含義 | 比較運算符 | 含義 |
---|---|---|---|
/ | 並/或 | 大於 | |
/ | 交/與 | < | 小於 |
笛卡爾積 | 小等於 | ||
- | 差 | 大等於 | |
非 | = | 等於 |
特殊操作還有四個:
運算符 | 含義 | 運算符 | 含義 |
---|---|---|---|
(讀作"“希格瑪”") | 選擇 | 或 | 投影 |
(讀作"join") | (自然)連接 | 除 |
涉及到連接,除了自然連接,就必須提到幾種擴展連接方式:
運算符 | 含義 | 運算符 | 含義 |
---|---|---|---|
連接(條件連接) | 自然連接 | ||
左外連接 | 右外連接 |
這幾種連接方式將在後面和笛卡爾積做集中區分。
理解關係代數符號
從一道例題出發:
① 投影
要理解 就要先從投影說起。
或 被稱爲投影操作,但我更偏向於把它稱爲去冗。
什麼是投影?假設我現在有兩個表:學生信息(學號,姓名,班級)
和學生成績(學號,成績,班級)
,如果以學號、姓名、班級、成績爲四個軸建立座標系,兩個表中同一個學生的信息會被映射到兩個點。舉一個例值:
(左)學號 | (左)姓名 | (左)班級 | (右)學號 | (右)成績 | (右)班級 |
---|---|---|---|---|---|
32 | 張三 | 1401032 | 32 | 90 | 1401032 |
你會發現學號
和班級
在左右兩個表中都重合了,如果我們只看兩個表中的學號
和班級
,那麼左右兩個表中的這個值都會是一樣的,也就是被投影到了同一個點——
(左)學號 | (左)班級 | (右)學號 | (右)班級 | ||
---|---|---|---|---|---|
32 | 1401032 | 32 | 1401032 |
如果每一個學生都有成績或每一個有成績的學生都登記到學生信息表中,那麼:
之所以說投影就是去冗,我們畫個圖會更直觀點,給出兩個關係R(X,Y)
——
X的值 | Y的值 |
---|---|
1 | 2 |
1 | 3 |
2 | 2 |
製圖如下:
如果做操作,則前兩個點(綠線)則會投影到同一個地方,也就完成了一次“去冗”,丟掉了我們所不關心的Y軸信息;如果做操作,則第一和第三個點(黃線)也被投影到同一個點。用SQL語句就是:select distinct X from R
。
當我們通過select操作選擇出一堆數據時,難免會有不少如點
(1,3,...)
和點(1,2,...)
這樣的結果值,我們現在只想知道它們在X軸上等於幾,則直接對X軸投影,即可只得到一個(1)...
。
注意,投影會改變數據的維度,比如上面例子中兩列的表經過投影只留下了一個屬性列。
特殊的,有若干個表經過複雜的操作(連接、選擇等等),可能會產生兩條一摸一樣的數據,這時候使用符號(讀作“德爾塔”)表示去除R中相同的元組(值、行、數據)。
② 選擇
和都有特殊記法,如題目中的 指的是選擇R關係中的屬性列,略去屬性列名而採用列序號表示,等價於。配合比較、集合/邏輯運算符等,則可以進一步附加選擇時的條件,如:。
選擇的SQL語句爲:select A1 from R [where ....]
。這部分內容比較簡單,主要需要了解的就是剛剛提到的特殊記法,會在很多題目中出現。
③ 連接
連接是一個非常複雜的問題,主要有四種:自然連接、條件連接、左外連接和右外連接。同時還會有一個笛卡爾積在其中混淆視聽。
1.笛卡爾積
笛卡爾積和連接最大的區別在於:不會合並任何一個列(屬性),而是完整地做了一次排列組合操作。用圖來表示:(圖中A、B、1、2、3均爲表的某個值,甲表和乙表做笛卡爾乘積( )得到丙表,甲表和乙表有且只有一列屬性列,以黑/藍圓圈表示)
假如有和,則 等於共列,如果R中有7條數據,S中有8條數據,中會有條數據。
這時候我們反過來想一下,如果做,就又經過投影得到了甲表。
2.自然連接
自然連接和笛卡爾積的區別在於,會合並相同的列,並以相同的列的值作爲兩個表的合併依據。
上圖中甲表和乙表由於不存在相同的值和列,因此做自然連接會得到一個空表。
以學生信息(學號,姓名,班級)
和學生成績(學號,成績,班級)
這兩個表爲例,做它們的自然連接:
注意到學生信息表
中的王五
的信息由於沒法跟學生成績表
中找到(學號,班級)
的匹配,因此在合成表中直接被刪除了(理解成王五缺考了)。我們把這種找不到匹配的值叫做懸浮元組,懸浮元組會在左右外連接中用到。
同樣,對這個合成後的表做去冗操作,就會得知沒有缺考的人都是1班的(簡化一下問題,我們假設已知只有兩個班級且有一個班級的人全部缺考了)。
3.條件連接( 連接)
條件連接是一種先經過笛卡爾乘積再進行選擇的操作,例如上文中學生信息和學生成績的例子(分別記爲R和S):(別忘了上文中提到的——和都有特殊記法)
顯然 ,等值條件連接可以產生與自然連接相近的結果,但依舊會保留一些冗餘的列(這也是笛卡爾乘積與自然連接最大的差距之處);大部分情況下,這種冗餘無法通過消除,詳見下圖。
我們畫個圖:
同樣,條件可以有很多種,上面的例子是左右表學號和班級相同,你也可以只單單把條件設爲成績大於95,即 ,那麼最終結果就是:(顯然這種連接出來的結果並不能反映學生成績的真實意義,除非再做一次比對班級學號的選擇)
學號 | 姓名 | 班級 | 學號 | 成績 | 班級 |
---|---|---|---|---|---|
1 | 張三 | 1 | 2 | 100 | 1 |
2 | 李四 | 1 | 2 | 100 | 1 |
3 | 王五 | 2 | 2 | 100 | 1 |
等值連接:就是等值連接,是條件連接的一個特例。與自然連接不同,雖然都需要尋找等值的屬性,但不像自然連接一樣只保留一個同名屬性列。
4.外連接
外連接分爲左/右外連接。某種意義上,可以把外連接看成是自然連接的一種擴充。
上文中提到了懸浮元組,還是以學生信息和學生成績爲例子,在自然連接中,懸浮元組會被直接丟棄,而外連接則會根據左右情況予以保留。
例如:
會發現左表的懸浮元組在左外連接中得以保留,右表由於沒有懸浮元組,因此右外連接時和自然連接結果相同。其SQL語句一般爲:select A1 from R left join S on R.學號=S.學號 and R.班級=S.班級
。
除此之外還有全外連接(
full join
),即同時保留兩邊的懸浮元素,在以上例子中,全外連接的結果和左外連接相同,符號一般爲:,不是很重要。
5.自連接
除此之外還有一種叫自連接的操作,剛剛在選擇連接中提到:
之所以是近似相等就是因爲保留了R的學號、班級和S的學號、班級這些冗餘信息,且無法使用消除,那麼使用自連接就可以把它變成完全相等。
自連接不引入任何新符號,相應的SQL語句如:
select * from R as a, R as b where a.A1=b.A1
。僅作了解即可。
例題求解
回到剛剛所說的例題:
求等價爲…?
- 用人話來解釋這個式子,就是R和S自然連接後,選擇滿足小於2017和=95的數據,然後只保留和中不重複的值,最終關係的結構爲。
先看第一個選項,我們應當知道形成的新關係爲,其中自然連接消去(合併)了二者中相同的屬性列,那麼根據的特殊記法,此處的等價於,對比原式顯然錯誤(邏輯錯誤)。
再看第二、三個選項。根據的特殊記法,首先排除C答案。因爲S關係只有三個屬性列,而顯然不能成立。
接着,先來想想笛卡爾乘積後會變成什麼樣的結構。
顯然其結構爲,共六個屬性列。
第二個選項中 其實是,從語義上來說也是選擇滿足小於2017和=95的數據,並通過最外層的投影完成了的映射。
- 另外,一個比較常見的化簡是:等價於。
但別忘了笛卡爾乘積不會根據相同值進行匹配消去相同屬性列。所以,第四個選項和第二個選項相比較,多了的操作,在笛卡爾乘積之後手動進行了選擇,即一次等值連接,讓其近似相等於自然連接。
綜合以上,做這種題的思路大概就是:
- 把原式最終得到的關係寫出來
- 把跟原式與或非邏輯不相符合的邏輯錯誤選項淘汰
- 根據最終關係淘汰不合理的選項
- 處理映射、選擇中的邏輯陷阱。常見的陷進如上文中的等值連接和自然連接的差別等。