关系代数除法与其对应的 SQL 语句

用下表来解释内容。
sc 表:

sno

cno

grade

201215121

1

92

201215121

2

85

201215121

3

88

201215122

2

90

201215122

3

80

201215123

3

90

基本形式

可用 sql server除法结果为啥未0_sql 来表示除法中的一般情况。
这是因为,假如 sql server除法结果为啥未0_元组_02
sql server除法结果为啥未0_sql server除法结果为啥未0_03
这样一来,
sql server除法结果为啥未0_数据库_04 表示在 sql server除法结果为啥未0_mysql_05 中却不在 sql server除法结果为啥未0_数据库_06 中的列
sql server除法结果为啥未0_mysql_07 表示既在 sql server除法结果为啥未0_mysql_05 中也在 sql server除法结果为啥未0_数据库_06 中的列
sql server除法结果为啥未0_sql server除法结果为啥未0_10 表示在 sql server除法结果为啥未0_数据库_06 中却不在 sql server除法结果为啥未0_mysql_05 中的列
可以将关系 sql server除法结果为啥未0_mysql_05 看成只有 sql server除法结果为啥未0_sql_14 两列,sql server除法结果为啥未0_数据库_06 亦然,而例如判定 sql server除法结果为啥未0_mysql_05 中两个元组的 sql server除法结果为啥未0_mysql_07 属性是否相等,则是判定两个元组的 sql server除法结果为啥未0_mysql_07

象集

对关系代数除法的解释,需要借助一个叫做象集的概念。
sql server除法结果为啥未0_mysql_19 表示 t 是 R 的一个元组
sql server除法结果为啥未0_sql_20 表示元组 sql server除法结果为啥未0_mysql_21 中相应于属性 sql server除法结果为啥未0_数据库_04 的一个分量(sql server除法结果为啥未0_元组_23 吧大概)
sql server除法结果为啥未0_mysql_24,则 sql server除法结果为啥未0_数据库_25 在 R 中的象集为:
sql server除法结果为啥未0_元组_26

例如在 sc 表中,201215121 的象集就是

cnograde192285388

和 group by 有相似之处

关系代数除法的定义

除法的定义式为(设除法的结果是关系 sql server除法结果为啥未0_sql_27):

sql server除法结果为啥未0_sql server除法结果为啥未0_28

其中,sql server除法结果为啥未0_元组_29,也就是说,是 sql server除法结果为啥未0_sql server除法结果为啥未0_30sql server除法结果为啥未0_mysql_05

我这样解释除法:

  • 遍历 sql server除法结果为啥未0_元组_32 中的每一个元组时,考察其 sql server除法结果为啥未0_sql_33
  • 如果如果 sql server除法结果为啥未0_数据库_34 中的整个 sql server除法结果为啥未0_mysql_35 行是一个元组中的 sql server除法结果为啥未0_sql_33 分量在 sql server除法结果为啥未0_元组_32 中的象集的子集,则输出这个 sql server除法结果为啥未0_sql_33
  • 对所有输出的 sql server除法结果为啥未0_sql_33

按除法的定义,可知:

  • sql server除法结果为啥未0_mysql_40
  • sql server除法结果为啥未0_元组_41

笛卡尔积的逆运算是这种除法,但这种除法的逆运算不是笛卡尔积,毋宁说想找到这个除法的逆运算是困难的。

例如:
给定这样一个表 sql server除法结果为啥未0_数据库_06

cno

1

2

考虑 sql server除法结果为啥未0_元组_43
考虑 sql server除法结果为啥未0_sql_44 的第一行,201215121 在 sql server除法结果为啥未0_sql_44

cno

1

2

3

显然,sql server除法结果为啥未0_数据库_06 是这个象集的子集,因此第一行中的 sql server除法结果为啥未0_sql_47 会输出,第二、三行亦然。
但是第 4 ~ 6 行则不会输出,因为 sql server除法结果为啥未0_数据库_06 不是这几行中的 sql server除法结果为啥未0_sql_47

因此,sql server除法结果为啥未0_元组_43 的结果就是:只有一列 sql server除法结果为啥未0_sql_47,只有一行 201215121 的表。
而显然,sql server除法结果为啥未0_数据库_52 只会有两行,因此不等于 sql server除法结果为啥未0_sql_44

Mysql 实现关系代数除法

Mysql 并不提供直接实现除法的语法,但是可以通过现有语法实现和除法相同的效果。

预计使用 mysql 的 where 语句+条件表达式的形式来实现除法。
首先考察如何理解 mysql 中的 where 语句:

  • 遍历这个表中的每一个元组
  • 判定遍历到这个元组时 where 语句是否为真
  • 如果为真,则输出这个元组

再来考察除法的定义式与我对除法的解释:

sql server除法结果为啥未0_mysql_54

  • 遍历 sql server除法结果为啥未0_元组_32 中的每一个元组时,考察其 sql server除法结果为啥未0_sql_33
  • 如果如果 sql server除法结果为啥未0_数据库_34 中的整个 sql server除法结果为啥未0_mysql_35 行是一个元组中的 sql server除法结果为啥未0_sql_33 分量在 sql server除法结果为啥未0_元组_32 中的象集的子集,则输出这个 sql server除法结果为啥未0_sql_33
  • 对所有输出的 sql server除法结果为啥未0_sql_33

我的解释提到了遍历的概念且解释了每次遍历时的判定方法

现尝试给出某一 sql server除法结果为啥未0_sql server除法结果为啥未0_63 满足条件的逻辑表达式:
sql server除法结果为啥未0_sql_64
这样一来,可以用这样的 mysql 语句实现 sql server除法结果为啥未0_sql server除法结果为啥未0_65

select A.X from R as A
where not exists
    select * from R as B(
    where B.Y in (
        select S.Y from S
    )and not exists(
        select * from R as C
        where A.X=C.X and B.y=C.Y
    )
)

值得一提的是,这里的 B.Y in(...) 可以替换成别的逻辑表达式,表示 sql server除法结果为啥未0_sql server除法结果为啥未0_66

测试:
尝试使用 Mysql 实现 sql server除法结果为啥未0_元组_43

select distinct A.sno from (select sno, cno from sc) as A
where not exists(
    select * from (select sno, cno from sc) as B
    where B.cno in ('1', '2') and not exists(
        select * from (select sno, cno from sc) as C
        where A.sno = C.sno and B.cno = C.cno
    )
)

当然,这是严格按照除法定义写出的,也可以直接写成:

select distinct A.sno from sc as A
where not exists(
    select * from sc as B
    where B.cno in ('1', '2') and not exists(
        select * from sc as C
        where A.sno = C.sno and B.cno = C.cno
    )
)

这是因为在实际上的判断语句中并没有涉及到 sc 中 sno 和 cno 以外的列。

两个 mysql 语句输出均符合预期:

+-----------+
| sno       |
+-----------+
| 201215121 |
+-----------+

例题

我开始关注的关系代数除法是因为这样一道题:求至少选修了学号为S1所选修的全部课程的学生学号。

给出的示例表就是这道题所用的表。

答案是:

set @S1 = "201215122";

select distinct sno from sc as x
where not EXISTS(
    select * from sc as y
    where y.sno=@S1 and not exists(
        select * from sc as z 
        where z.sno=x.sno and z.cno=y.cno
    )
);

观察题意,只需选出 S1 所选的全部 cno,与 sc 表相除即可得到答案。
这里判断 y.sno=@S1 就是判定 sql server除法结果为啥未0_元组_68

其他解法

select sno from
(
    select a.sno, COUNT(b.cno) as c from
    (
        select sc.cno from sc
        where sc.sno = @S1
    )as b
    join sc as a
    where a.cno = b.cno
    group by sno
)as ttt 
join (
    select MAX(ttt2.c) as ma from (
        select a.sno, COUNT(b.cno) as c from
        (
            select sc.cno from sc
            where sc.sno = @S1
        )as b
        join sc as a
        where a.cno = b.cno
        group by sno
    ) as ttt2
) as af
where c = ma and sno <> @S1;

计算每个人的 cno 的集合与 S1 的 cno 的交集,如果这个交集的元素个数与 S1 的 cno 数量相同,说明 S1 的 cno 是这个象集的子集,满足条件,可输出。也是实现除法的另一种方法,你可以考虑一下这种思路来提出一种新的用 sql 语句实现除法的方法。