由於之前的排版很chishi,所以就改了一下,把前面一部分移動到了新的文章《元組關系演算(從集合的角度深入淺出)》
例題(不嚴謹,更嚴謹的看這里:蘊含式) ===》
注:這里有如下說明 > 關於全稱量詞需要用到“蘊含式”,所以就不嚴謹(但並不是說有錯誤)。我們知道我們提出這樣一個理論的目的是為了更好的運用於實際,在實際中我們是用的SQL語句來實現的,這樣寫是很難轉換為SQL語句的,所以就不提倡大家用這樣的方法寫,上面就貼出來一個全新的、能夠很容易就轉換為SQL語句的元組關系演算(順便介紹了“蘊含式”——百度百科)。
用戶提供的5張表 ===》
| 描述的實體 | 表的中文名 | 表的數據結構 |
| Teacher | 教師關系表 | T(TNo, TN, Dept) |
| Student | 學生關系表 | S(SNo, SN, Dept) |
| Class | 課程關系表 | C(CNo, CN, CT) |
| Student_Class | 學生-選課關系表 | SC(SNo, CNo, Score) |
| Teacher_Class | 教師-授課關系表 | TC(TNo, CNo) |
(Ⅰ)"全部都有" VS "至少沒一"(即:A ∪ B =?= A,或者表述為A ?⊇ B)
(1). 查詢選修了'李力'老師所教授的全部課程的學生的學號、姓名
粗略關系代數表達式為:
Π(SNo, SN)(S) ⋈ Π(SNo, CNo)(SC) ÷ ΠCNo{ΠTNo[σTN='李力'(T)] ⋈ TC};
元組演算表達式為: {
new_s(2) | 【(∃t)(∃sc)(∃s)】
【T(t) Λ TC(tc) Λ SC(sc) Λ S(s)】 Λ
【
t[2] = '李力' Λ # 在T表中選取TN字段為'李力'的元組;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行自然連接,這時得到了李力老師教授的所有課程的課程號的集合:Lili_C;
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行自然連接;
(∀tc) tc[2] = sc[2] Λ # 對於任意的(∀)tc ∈ TC,總是存在(∃)sc ∈ SC,滿足tc[2] = sc[2],即Lili_C ⊆ SNocno(所在關系為Π(SNo, CNo)(SC));
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
(2). 查詢至少有一門'李力'老師所教授的課程沒有選過的學生的學號、姓名(這名學生沒有選擇李力老師教授的一門或以上的課程)
粗略關系代數表達式為:
Π(SNo, SN)(S) - Π(SNo, SN)(S) ⋈ Π(SNo, CNo)(SC) ÷ ΠCNo{ΠTNo[σTN='李力'(T)] ⋈ TC};
在上一個題目中,我們求的是"選修了'李力'老師所教授的全部課程的學生",所以選擇"全稱量詞∀"來表述命題p:∀tc∈TC,∃sc∈SC使得tc[2] = sc[2]成立。而現在我們是"沒有選擇李力老師教授的一門或以上的課程的學生",即求¬p:∃tc∈TC,∀sc∈SC使得tc[2] ≠ sc[2]成立。
元組演算表達式為: {
new_s(2) | 【(∃t)(∃tc)(∀sc)(∃s)】
【T(t) Λ TC(tc) Λ SC(sc) Λ S(s)】 Λ
【
t[2] = '李力' Λ # 在T表中選取TN字段為'李力'的元組;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行自然連接,這時得到了李力老師教授的所有課程的課程號的集合:Lili_C;
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行自然連接;
tc[2] ≠ sc[2] Λ # 存在tc ∈ TC,對於任意的sc ∈ SC,都滿足tc[2] ≠ sc[2],即TC ∩ SC ≠ TC;
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
--(3). 查詢(至少)教授'數據庫'和'計算機基礎'這兩門課程的老師的姓名(在老師教授的課程的課程編號集合中包含{'數據庫'的編號, '計算機基礎'的編號}) ===》
答:粗略關系代數表達式為: ===》
Π(TNo, CNo)[Π(TNo, TN)(T) ⋈ Π(TNo, CNo)(TC)] ÷ ΠCNo[σcn='數據庫' ∨ cn='計算機基礎'(C)];
元組演算表達式為: {
new_t(1) | (∃t)(∃tc)
【T(t) Λ TC(tc) Λ C(c)】 Λ
【
(∃c) (c[2] = '數據庫' ∨ c[2] = '計算機基礎') Λ # 在C表中選取CN字段為'數據庫'的元組,其實是得到了'數據庫'課程的編號sjk_C;
(∀c) (tc[2] = c[1]) Λ # ∀c∈C,∃tc∈TC,滿足tc[2] = c[1],即TC ⊇ C;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行連接;
new_t[1] = t[2] Λ # 將T表投影到TN字段,新表的第一個屬性為TN;
】
}
--(4). 查找至少沒有教授"數據庫"和"計算機基礎"這倆門課程中的一門的老師的姓名 ===》
答:關系代數: ===》
ΠTN(T) - Π(TNo, CNo)[Π(TNo, TN)(T) ⋈ Π(TNo, CNo)(TC)] ÷ ΠCNo[σcn='數據庫' ∨ cn='計算機基礎'(C)];
這個問題乍一看"WTF",那我們"正難則反",考慮其反面:"全部都選"。所以¬p: ∀tc∈TC和sc∈SC,都滿足tc[2] ≠ sc[2] ===> p:∃tc∈TC和sc∈SC,滿足tc[2] = sc[2],即A ∩ B ≠ ∅。
元組演算表達式為: {
new_t(1) | (∃t)(∃c)(∀tc)
【T(t) Λ TC(tc) Λ C(c)】 Λ
【
c[2] = '數據庫' ∨ c[2] = '計算機基礎' Λ # 在C表中選取CN字段為'數據庫'的元組,其實是得到了'數據庫'課程的編號sjk_C;
tc[2] ≠ c[1] Λ # ∃c∈C,∀tc∈TC都滿足tc[2] ≠ c[1],即A ∪ B ≠ A;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行連接;
new_t[1] = t[2] Λ # 將T表投影到TN字段,新表的第一個屬性為TN;
】
}
(Ⅱ)"全部都沒" VS "至少有一"(即:A ∩ B =?= ∅)
--(1). 查詢沒有選修'李力'老師的課程的(全部)學生的學號、姓名(一門李力老師教授的課程都沒有選的學生) ===》
答:粗略關系代數表達式為(這個用關系代數比較難表達,所以我們可以看反面:"至少選了一門"。然后再用總的減去它):
Π(SNo, SN)(S) - Π(SNo, SN)(ΠCNo{ΠTNo[σcn='李力'(T)] ⋈ TC} ⋈ [Π(CNo, SNo)(SC) ⋈ Π(SNo, SN)(S)]);
這個問題可以表述為A ∩ B = ∅(對於A、B中的所有元素,都滿足a ≠ b),這里的A即為{某個學生選課的編號集合},B即為{李力老師教授課程的課程編號集合}
元組演算表達式為: {
new_s(2) | 【(∃t)(∀tc)(∀sc)(∃s)】
【T(t) Λ TC(tc) Λ SC(sc) Λ S(s)】 Λ
【
t[2] = '李力' Λ # 在T表中選取TN字段為'李力'的元組;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行連接,得到李力老師教授的全部課程的課程編號集合;
tc[2] ≠ sc[2] Λ # ∀tc∈TC和sc∈SC,都滿足tc[2] ≠ sc[2];
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行自然連接;
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
--(2). 查詢選修了'李力'老師的課程的(全部)學生的學號、姓名(至少選修了一門李力老師教授的課程的學生) ===》
答:粗略關系代數表達式為: ===》
Π(SNo, SN)(ΠCNo{ΠTNo[σcn='李力'(T)] ⋈ TC} ⋈ [Π(CNo, SNo)(SC) ⋈ Π(SNo, SN)(S)]);
很懵逼,那老規矩"正難則反",考慮其反面:"全部都沒選",發現正好是(1)中解決的(真巧吭,難道是故意安排的,誰知道呢?),所以¬p: ∀tc∈TC和sc∈SC,都滿足tc[2] ≠ sc[2] ===> p:∃tc∈TC和sc∈SC,滿足tc[2] = sc[2],即A ∩ B ≠ ∅。
元組演算表達式為: {
new_s(2) | 【(∃t)(∃tc)(∃sc)(∃s)】
【T(t) Λ TC(tc) Λ SC(sc) Λ S(s)】 Λ
【
t[2] = '李力' Λ # 在T表中選取TN字段為'李力'的元組;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行連接,得到李力老師教授的全部課程的課程編號集合;
tc[2] = sc[2] Λ # ∃tc∈TC和sc∈SC,滿足tc[2] = sc[2],即在TC表中存在某個元組tc,總能在SC表中找到某個元組sc,滿足tc[2] = sc[2];
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行自然連接;
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
--(3). 查詢教授'數據庫'這門課程的(全部)老師的編號、姓名(在老師教授的課程的課程編號集合中至少存在數據庫這門課程的編號) ===》
答:粗略關系代數表達式為: ===》
Π(TNo, TN){ΠCNo[σcn='數據庫'(C)] ⋈ TC ⋈ Π(TNo, TN)(T)};
元組演算表達式為: {
new_t(2) | 【(∃c)(∃t)(∃tc)】
【T(t) Λ C(c) Λ TC(tc)】 Λ
【
c[2] = '數據庫' Λ # 在C表中選取CN字段為'數據庫'的元組;
tc[2] = c[1] Λ # ∃tc∈TC和c∈C,滿足tc[2] = c[1],即'數據庫'課程的編號sjk_C存在於這位老師教授課程的課程編號集合中;
tc[1] = t[1] Λ # 通過TNo字段將T表與TC表進行連接;
new_t[1] = t[1] Λ # 將T表投影到TNo字段,新表的第一個屬性為TNo;
new_t[2] = t[2] Λ # 將T表投影到TN字段,新表的第二個屬性為TN;
】
}
--(4). 查找沒有教授"數據庫"這門課程的老師的姓名('數據庫'這門課程全都不存在於老師的教授課程編號集合中) ===》
答:粗略關系代數表達式為(考慮反面:"至少有一個'數據庫'的課程存在於老師的教授課程編號集合中"):
ΠTN(T) - ΠTN{ΠCNo[σcn='數據庫'(C)] ⋈ TC ⋈ Π(TNo, TN)(T)};
元組演算表達式為: {
new_t(1) | (∃t)(∀tc)(∀c)
【T(t) Λ TC(tc) Λ C(c)】 Λ
【
c[2] = '數據庫' Λ # 在C表中選取CN字段為'數據庫'的元組,其實是得到了'數據庫'課程的編號sjk_C;
tc[2] ≠ c[1] Λ # ∀tc∈TC和c∈sjk_C,都滿足tc[2] ≠ c[1];
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行連接;
new_t[1] = t[2] Λ # 將T表投影到TN字段,新表的第一個屬性為TN;
】
}
3. "全部都有" VS "全部都沒" (注意:這倆並不是對立事件!!!)
--(1). 查詢選修了所有課程的學生的學號、姓名(在C表中任取一個課程都能在這個學生的SC表中找到對應的CNo ===> ∀c∈C,c∈在集合π(SNo, CNo)(SC)中SNo的像集CNosno) ===》
答:粗略關系代數表達式為: ===》
Π(SNo, SN)(S) ⋈ Π(SNo, CNo)(SC) ÷ ΠCNo(C)
元組演算表達式為: {
new_s(2) | 【(∀c)(∃sc)(∃s)】
【C(c) Λ S(s) Λ SC(sc)】 Λ
【
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行連接,這時其實可以得到所有選課學生的課程編號;
sc[2] = c[1] Λ # 對於任意的c ∈ C,總是存在(∃)sc ∈ SC,滿足sc[2] = c[1],即πCNo(C) ⊆ SNocno(所在關系為π(SNo, CNo)(SC));
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
--(2). 查詢沒有選修一門課程的學生的學號、姓名(比如:1805xxxxx04, SimbaWang) ===》
答:粗略關系代數表達式為(老規矩"正難則反":"選修了課程的學生"): ===》
ΠSN(S) - ΠSN[Π(SNo)(SC) ⋈ Π(SNo, SN)(S)]
元組演算表達式為: {
new_s(2) | 【(∀c)(∀sc)(∃s)】
【C(c) Λ S(s) Λ SC(sc)】 Λ
【
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行連接,這時其實可以得到所有選課學生的課程編號;
sc[2] ≠ c[1] Λ # 對於任意的c ∈ C和sc ∈ SC,都滿足sc[2] ≠ c[1],即這兩者的交集為∅;
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
--(1). 查詢選修了'李力'老師所教授的全部課程的學生的學號、姓名 ===》
答:粗略關系代數表達式為: ===》
Π(SNo, SN)(S) ⋈ Π(SNo, CNo)(SC) ÷ ΠCNo{ΠTNo[σTN='李力'(T)] ⋈ TC};
元組演算表達式為: {
new_s(2) | 【(∃t)(∃sc)(∃s)】
【T(t) Λ TC(tc) Λ SC(sc) Λ S(s)】 Λ
【
t[2] = '李力' Λ # 在T表中選取TN字段為'李力'的元組;
t[1] = tc[1] Λ # 通過TNo字段將T表與TC表進行自然連接,這時得到了李力老師教授的所有課程的課程號的集合:Lili_C;
s[1] = sc[1] Λ # 通過SNo字段將SC表與S表進行自然連接;
(∀tc) tc[2] = sc[2] Λ # 對於任意的(∀)tc ∈ TC,總是存在(∃)sc ∈ SC,滿足tc[2] = sc[2],即Lili_C ⊆ SNocno(所在關系為Π(SNo, CNo)(SC));
new_s[1] = s[1] Λ # 將S表投影到SNo字段,新表的第一個屬性為SNo;
new_s[2] = s[2] Λ # 將S表投影到SN字段,新表的第二個屬性為SN;
】
}
