SQL简单语句的理解问题

我的问题:为什么这句语句能得到想要的结果?EXCEPT和关联子查询在这句语句中是怎么发挥效果的?
还有没有别种写法?
第一个表名Skills
内容是

 skill
--------
 Oracle
 UNIX
 Java

第二个表名EmpSkills
内容是

  emp   | skill
--------+--------
 一号   | Oracle
 一号   | UNIX
 一号   | Java
 一号   | C#
 二号   | Oracle
 二号   | UNIX
 二号   | Java
 三号   | UNIX
 三号   | Oracle
 三号   | PHP
 三号   | Perl
 三号   | C++
 四号   | Perl
 五号   | Oracle

要求是找出掌握Skill三个领域的员工,
结果是得到一号、二号。
语句是:

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

结果是:

 emp
------
 一号
 二号
阅读 4.5k
3 个回答

这段语句体现的是关系除法,
Skills中的skill是除数,
EmpSkills中的skill是被除数。
对于一号来说:得到空集合

得到的是空集合。

对于三号来说:还有Java

还有Java。

从而用NOT EXISTS达到想要的结果。
参考:SQL关系除法的思考

1、先执行的是括号里的语句:
依次是:
SELECT skill FROM EmpSkills ES2 where ES2.emp ='一号';
SELECT skill FROM EmpSkills ES2 where ES2.emp ='二号';
SELECT skill FROM EmpSkills ES2 where ES2.emp ='三号';
SELECT skill FROM EmpSkills ES2 where ES2.emp ='四号';
SELECT skill FROM EmpSkills ES2 where ES2.emp ='五号';

然后,EXCEPT指的是:
存在于前面(Skill表skill字段)中,而不存在于后面(EmpSkills ES2表skill字段),这里@SJkun 说得很好,就是关系除法,

执行的是:
(SELECT skill FROM Skills) except (SELECT skill FROM EmpSkills ES2 where ES2.emp ='一号');
.
.
.
(SELECT skill FROM Skills) except (SELECT skill FROM EmpSkills ES2 where ES2.emp ='五号');
那么就有三号不会JAVA技能、四号那3个全不会、五号UNIX和JAVA技能不会。

2、括号里执行完,结果集就有3个结果:

emp
三号
四号
五号

3、然后看外面:
SELECT DISTINCT emp
FROM EmpSkills ES1
WHERE NOT EXISTS(结果集);

注意最后一行“NOT EXISTS(结果集)”,这个我自己理解成中文的意思就是:不存在这个结果集的剩下的结果,自然只有“一号”和“二号”了。

emp
一号
二号
新手上路,请多包涵

对任意的 $emp_i$
k:$emp_i$ 的 一个 skill
A:skills 中 skill 的集合
B:empskills 中 $emp_i$ 的 skill 的集合:

$$ \begin{align*} &\forall k \in A, A \subset B \\ &\downarrow\\ &\forall k \in A, k\in B \Leftrightarrow \forall k \notin B, k\notin A \end{align*} $$

所以

只要选择出所有满足 $\forall k \notin B, k\notin A$ 即可。

不满足的情况:$\exists k \in A, k\notin B$

这种情况的否定就是所求的结果:$\neg\exists k, (k \in A, k\notin B)$

SELECT DISTINCT
    emp
FROM
    EmpSkills AS es1
WHERE
    NOT EXISTS( SELECT 
            skill
        FROM
            skills          
        WHERE
            skill NOT IN (SELECT 
                    skill
                FROM
                    EmpSkills AS es2
                WHERE
                    es1.emp = es2.emp));
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题