第3章_关系数据库标准语言(SQL)_006_由元组关系演算到SQL Command_002_案例_02_以'李力'老师教授的课程为准,学生的5种选课情况
01_查询选修了'李力'老师教授的全部课程的学生的学号、姓名;
02_查询至少有一门'李力'老师所教授的课程没有选过的学生的学号、姓名(这名学生没有选择李力老师教授的全部课程);
03_查询一门'李力'老师所教授的课程都没有选的学生的学号、姓名;
04_查询至少选修了一门'李力'老师所教授的课程的学生的学号、姓名;
05_学生只选修了'李力'老师的全部课程;
01_查询选修了'李力'老师教授的全部课程的学生的学号、姓名 ===》
{new_s(2) |
∃s(
s(S) Λ
∀tc(
tc(TC) Λ
∃t(
t(T) Λ
t.TNo = tc.TNo Λ
t.TN = '李力'
) → ∃sc(
sc(SC) Λ
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
) Λ
new_s[1] = s[1] Λ
new_s[2] = s[2]
)
}
经过化简得到:
{new_s(2) |
∃s(
¬【∃tc(
∃t(
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
¬【∃sc(
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)】
)】
)
}
按照简化后的“元组关系演算式”得出SQL语句:
SELECT SNo, SN
FROM S
WHERE
NOT EXISTS (
SELECT *
FROM TC
WHERE
EXISTS (
SELECT *
FROM T
WHERE
T.TN = '李力' AND
TC.TNo = T.TNo
)
AND
NOT EXISTS (
SELECT *
FROM SC
WHERE
SC.SNo = S.SNo AND
SC.CNo = TC.CNo
)
)
02_查询至少有一门'李力'老师所教授的课程没有选过的学生的学号、姓名(这名学生没有选择李力老师教授的全部课程) ===》
{new_s(2) |
∃s(
s(S) Λ
∃tc(
tc(TC) Λ
∃t(
t(T) Λ
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
∀sc ¬(
sc(SC) Λ
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
) Λ
new_s[1] = s[1] Λ
new_s[2] = s[2]
)
}
经过化简得到:
{new_s(2) |
∃s(
∃tc(
∃t(
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
¬【∃sc (
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)】
) Λ
new_s[1] = s[1] Λ
new_s[2] = s[2]
)
}
按照简化后的“元组关系演算式”得出SQL语句:
SELECT SNo, SN
FROM S
WHERE
EXISTS (
SELECT *
FROM TC
WHERE
EXISTS (
SELECT *
FROM T
WHERE
T.TN = '李力' AND
TC.TNo = T.TNo
)
AND
EXISTS (
SELECT *
FROM SC
WHERE
SC.SNo = S.SNo AND
SC.CNo = TC.CNo
)
)
03_查询一门'李力'老师所教授的课程都没有选的学生的学号、姓名 ===》
{new_s(2) |
∃s(
s(S) Λ
∀tc(
tc(TC) Λ
∃t(
t(T) Λ
t.TNo = tc.TNo Λ
t.TN = '李力'
) → ∀sc ¬(
sc(SC) Λ
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
) Λ
new_s[1] = s[1] Λ
new_s[2] = s[2]
)
}
经过化简得到:
{new_s(2) |
∃s(
¬【∃tc(
∃t(
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
∃sc(
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
)】
)
}
注释:这其实就是“查询至少选修了一门'李力'老师所教授的课程的学生的学号、姓名”的否定。
按照简化后的“元组关系演算式”得出SQL语句:
SELECT SNo, SN
FROM S
WHERE
NOT EXISTS (
SELECT *
FROM TC
WHERE
EXISTS (
SELECT *
FROM T
WHERE
T.TN = '李力' AND
TC.TNo = T.TNo
)
AND
EXISTS (
SELECT *
FROM SC
WHERE
SC.SNo = S.SNo AND
SC.CNo = TC.CNo
)
)
04_查询至少选修了一门'李力'老师所教授的课程的学生的学号、姓名 ===》
{new_s(2) |
∃s(
s(S) Λ
∃tc(
tc(TC) Λ
∃t(
t(T) Λ
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
∃sc(
sc(SC) Λ
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
) Λ
new_s[1] = s[1] Λ
new_s[2] = s[2]
)
}
经过化简得到:
{new_s(2) |
∃s(
∃tc(
∃t(
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
∃sc(
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
)
)
}
注释:这里的∃t和∃sc是可以合并的,依据“量词辖域的扩张和收缩”的第一点,并且∃t和∃sc互不影响,运用2次即可写成 ===》
【∃t, p(t)) Λ (∃sc, q(sc)】 ⇔ 【∃t, p(t) Λ ∃sc, q(sc)】 ⇔ 【∃t, ∃sc, p(t) Λ q(sc)】
∃t(
∃sc(
t.TNo = tc.TNo Λ
t.TN = '李力' Λ
s.SNo = sc.SNo Λ
sc.CNo = tc.CNo
)
)
进一步我们可以写成:【∃t∃sc, p(t, sc)】这样的形式(没有自由元组变元的二元谓词)。
拓展:在只含有“存在量词∃”或者只含有“全称量词∀”的SQL语句中,除了最后投影的表之外,其他的表可以任意交换顺序(因为最后是要投影S表)。依据为“多重量化及其等价式和蕴含式”,【∃x∃y, p(x, y)】与【∃y∃x, p(x, y)】含义相同。
全是全称量词:(p1, p2, ..., pn,两两不受对方辖域的影响,即相互之间可以看成是不受约束的自由元组变量)
(∀, ¬p1 → ∀, ¬p2 → ... → ∀, ¬pn)
⇔ ¬(∀, ¬p1 → ∀, ¬p2 → ... → ∀, ¬pn-1) ∨ (∀, ¬pn)
⇔ ¬(∀, ¬p1 → ∀, ¬p2 → ... → ∀, ¬pn-1) ∨ ¬(∃, pn)
⇔ ¬【(∀, ¬p1 → ∀, ¬p2 → ... → ∀, ¬pn-1) Λ (∃, pn)】
......
⇔ ¬【(∃, p1) Λ ... Λ (∃, pn)】
⇔ ¬【∃...∃, p1 Λ ... Λ pn】
按照简化后的“元组关系演算式”得出SQL语句:
SELECT SNo, SN
FROM S
WHERE
EXISTS (
SELECT *
FROM TC
WHERE
EXISTS (
SELECT *
FROM T
WHERE
T.TN = '李力' AND
TC.TNo = T.TNo
)
AND
EXISTS (
SELECT *
FROM SC
WHERE
SC.SNo = S.SNo AND
SC.CNo = TC.CNo
)
)
05_学生只选修了'李力'老师的全部课程 ===》
分析:p↔q ⇔ (p→q Λ q→p) ⇔ (pΛq) ∨ (¬pΛ¬q),虽然说可以进一步简化,但是在元组关系演算中我们通常使用第二个,这是因为p和q不好找。随时这样说,但是我们还是可以给出一个等价式:
¬{∃p【P(p) Λ ¬∃q【Q(q)】】 ∨ ∃q【Q(q) Λ ¬∃p【P(p)】】},按照德摩根律将{}去掉后得到 ===》
∀p¬【P(p) Λ ¬∃q【Q(q)】】 Λ ∀q¬【Q(q) Λ ¬∃p【P(p)】】:意思就是同事满足两个条件 ===》
1. 对于任意的p,不可能在p∈P的情况下,没有一个q∈Q使得Q(q)成立;
2. 对于任意的q,不可能在q∈Q的情况下,没有一个p∈P使得P(p)成立;
{new_s(2) |
∃s(
s(S) Λ
∀tc(
tc(TC) Λ
∃t(
t(T) Λ
t.TNo = tc.TNo Λ
t.TN = '李力'
) → ∃sc(
sc(SC) Λ
sc.CNo = tc.CNo Λ
s.SNo = sc.SNo
)
) Λ
∀sc(
sc(SC) Λ
s.SNo = sc.SNo → ∃tc(
sc.CNo = tc.CNo Λ
∃t(
t(T) Λ
t.TNo = tc.TNo Λ
t.TN = '李力'
)
)
)
new_s[1] = s[1] Λ
new_s[2] = s[2]
)
}
经过化简得到:
{new_s(2) |
∃s(
¬【∃tc(
∃t(
t.TNo = tc.TNo Λ
t.TN = '李力'
) Λ
¬【∃sc(
sc.CNo = tc.CNo Λ
s.SNo = sc.SNo
)】
)】 Λ
¬【∃sc(
s.SNo = sc.SNo Λ
¬【∃tc(
sc.CNo = tc.CNo Λ
∃t(
t.TNo = tc.TNo Λ
t.TN = '李力'
)
)】
)】
)
}
按照简化后的“元组关系演算式”得出SQL语句:(其中有一个变形,依据德摩根律)
SELECT SN, SNo
FROM S
WHERE NOT (
EXISTS (
SELECT *
FROM TC
WHERE
EXISTS (
SELECT *
FROM T
WHERE
T.TNo = TC.TNo AND
T.TN = '李力'
) AND
NOT EXISTS (
SELECT *
FROM SC
WHERE
S.SNo = SC.SNo AND
SC.CNo = TC.CNo
)
) OR
EXISTS (
SELECT *
FROM SC
WHERE
S.SNo = SC.SNo AND
NOT EXISTS (
SELECT *
FROM TC
WHERE
SC.CNo = TC.CNo AND
EXISTS (
SELECT *
FROM T
WHERE
T.TNo = TC.TNo AND
T.TN = '李力'
)
)
)
)