用 SQL 进行集合运算

书上很多SQL内容在MYSQL上不支持,比如EXPECT
1.监测两个表是不是完全相同

SELECT COUNT(*) AS row_cnt
  FROM ( SELECT *
           FROM tbl_A
         UNION
         SELECT *
           FROM tbl_B ) TMP;

如果结果和A表和B表的行数一样,说明A和B完全一样。因为UNION不加参数ALL会去掉重复的行。

  1. 用差集实现关系除法运算
EmpSkills.png

Skills.png
SELECT emp FROM EmpSkills LEFT JOIN Skills ON EmpSkills.skill = Skills.skill GROUP BY EmpSkills.emp
HAVING COUNT(Skills.skill) = (SELECT COUNT(*) FROM Skills)

还可以这样用求差集的方式进行运算,mysql 不支持。

SELECT DISTINCT emp
  FROM EmpSkills ES1
 WHERE NOT EXISTS
        (SELECT skill
           FROM Skills
         EXCEPT
         SELECT skill
           FROM EmpSkills ES2
          WHERE ES1.emp = ES2.emp);

3.寻找相等的子集

SupParts.png
SELECT SP1.sup AS s1, SP2.sup AS s2
  FROM SupParts SP1, SupParts SP2
 WHERE SP1.sup < SP2.sup                 -- 生成供应商的全部组合
   AND SP1.part = SP2.part               -- 条件1 :经营同种类型的零件
 GROUP BY SP1.sup, SP2.sup
HAVING COUNT(*) = (SELECT COUNT(*)       -- 条件2 :经营的零件种类数相同
                     FROM SupParts SP3
                    WHERE SP3.sup = SP1.sup)
   AND COUNT(*) = (SELECT COUNT(*)
                     FROM SupParts SP4
                    WHERE SP4.sup = SP2.sup);

自己没有想出来,这样的实际业务中,自己肯定会用php去做了。

解析:

我们检查一下这些供应组合是否满足以下公式:(A ⊆ B)且(A ⊇ B)=>(A = B)。这个公式等价于下面两个条件。
条件 1:两个供应商都经营同种类型的零件
条件 2:两个供应商经营的零件种类数相同(即存在一一映射)
条件 1 只需要简单地按照“零件”列进行连接,而条件 2 需要用 COUNT 函数来描述。

你可能感兴趣的:(用 SQL 进行集合运算)