SQL简单语句的理解问题

发布于 2022-09-01 23:28:03 字数 767 浏览 8 评论 0

我的问题:为什么这句语句能得到想要的结果?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
------
 一号
 二号

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怀中猫帐中妖 2022-09-08 23:28:03

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

得到的是空集合。

对于三号来说:还有Java

还有Java。

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

心奴独伤 2022-09-08 23:28:03

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
一号
二号
明明#如月 2022-09-08 23:28:03

对任意的 $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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文