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
------
一号
二号
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这段语句体现的是关系除法,
Skills中的skill是除数,
EmpSkills中的skill是被除数。
对于一号来说:
得到的是空集合。
对于三号来说:
还有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个结果:
3、然后看外面:
SELECT DISTINCT emp
FROM EmpSkills ES1
WHERE NOT EXISTS(结果集);
注意最后一行“NOT EXISTS(结果集)”,这个我自己理解成中文的意思就是:不存在这个结果集的剩下的结果,自然只有“一号”和“二号”了。
对任意的 $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)$
即