首先请看
http://topic.csdn.net/u/20070821/15/8a2dac05-51b8-4eb1-b41d-4fbe8a232c85.html
帖中从实际问题出发,讨论SQL语句中如何表示除法运算。
以下是问题的给出与简要描述:
然后下面有很多的回答,在这里我就不一一列出了。
先给出我的测试DDL与SQL语句。
解法一:
解法一使用的是《数据库系统概念(第五版)》上给出的正统转换方法:
r ¸ s = { t | t Î Õ R-S(r) Ù " u Î s ( tu Î r ) }
r ¸ s = ÕR-S (r) –ÕR-S ( (ÕR-S (r) x s) – ÕR-S,S(r))
我在这里做的就是把这段关系表达式转换成SQL语句就可以了。
在这里稍微解释一下这个关系表达式的由来。
整体思路就是先选出r集合中的(R-S)*(1)属性,然后与s集合进行笛卡尔操作,这时候得到的是(ÕR-S (r) x s) ,就是r集合中全部元组都能被选出来的理想情况*(2)(姑且这么说);然后减去集合r中的现实情况*(3)ÕR-S,S(r))(表示集合r属性的重新排列:而属性重新排列是集合进行差集运算所要求的),得到现实与理想的“差距”,并选出(R-S)的属性,就得到ÕR-S ( (ÕR-S (r) x s) – ÕR-S,S(r))。最后再用ÕR-S (r)(实际的集合)来与刚刚得出的ÕR-S ( (ÕR-S (r) x s) – ÕR-S,S(r))进行差集运算,得出符合理想(规定)的那些元组——而这些元组就是r ¸ s的结果了。
注:(1) (R-S)属性指的是r集合与s集合的关系模式的差集(即r集合中的字段集合与s集合中的字段集合的差集),其中S Í R,这是集
合除法规定的。
(2) 理想情况指的是所有元组都能成功配对的情况(通过笛卡尔积实现)。
(3) 现实情况指的是当前r集合中的实际元组情况。
解法二:
解法二的思路十分地独特,它巧妙地运用group by而大大简化了操作。
整体思路就是①先把r集合中的与s集合的相同字段(模式S)有相同值的元组提取出来(使用IN操作就可以了),②然后再对查询结果以它们相异的字段(模式R-S)分组,然后统计每个分组的COUNT是否等于期望的COUNT值(即s集合中的元组数),符合的就是结果了。
思路就这么简单,大家仔细想想就明白了。
解法三:
解法三就是传说中的双NOT EXISTS做法了,它的思路非常的直观,就是三层SELECT语句的嵌套。
整体思路就是,先求出ANO为256的BNO集合,然后与针对每一个相同ANO的BNO集合进行差集运算,如果结果为空集,那么就证明了该ANO的BNO集合包含了预期的BNO集合(即ANO为256的BNO集合),该集合可被输出,然后继续下一个ANO。
Note that X – Y = Ø Û X Í Y
其实就是以上这条公式的思路。
讲解中可能有不正确的地方,也希望大家可以指出~ ^_^
如果大家还有更多的好的写法,也欢迎大家留下~