今天學習到了如何通過NOT EXISTS來實現SQL中的關係除法,記錄一下以備日後溫習。
已經瞭解到,SQL現成的集合運算符有:UNION(並集)、EXCEPT(差集)、INTERSECT(交集)、CROSS JOIN(笛卡兒積),但關係除法是沒有現成函數的。
由於下面會用到,所以首先熟悉一下 EXISTS 的作用和用法:
例如下面的代碼實現的功能是找出在Table1、Table2中同時存在的全部id所對應的行
SELECT * FROM Table1 WHERE EXISTS( SELECT 1 FROM Table2 WHERE Table2.id=Table1.id) ;
/*內查詢中select後面的內容可以任意設定,哪怕NULL都OK,不影響結果,
因爲EXISTS函數的內查詢中返回的是布爾值True或False,
對應着查詢結果存在與否,與結果的實際內容無關*/
結果等同於IN語句
SELECT * FROM Table1 WHERE id IN(SELECTid FROM Table2);
接下來正式進入關係除法的演示部分,我們使用兩張表作爲示例用表。
Skill表:
-----
Skill
------
Oracle
UNIX
Java
EmpSkills表:
emp skill
--------------
相田 Oracle
相田 UNIX
相田 Java
相田 C#
神崎 Oracle
神崎 UNIX
神崎 Java
平井 UNIX
平井 Oracle
平井 PHP
平井 Perl
平井 C++
若田部 Perl
渡來 Oracle
以下這個問題就是除法的典型應用:
“從該表中選取出掌握了Skills表中所有3個領域的技術的員工”
方法一:
SELECT DISTINCT emp
FROM EmpSkills ES1
WHERE NOT EXISTS
(SELECT skill
FROM Skills
EXCEPT
SELECT skill
FROM EmpSkills ES2
WHERE ES1.emp = ES2.emp);--原書作者有筆誤
這樣我們就得到了包含相田和神崎2 人的結果。
emp
------
神崎
相田
通過另一種方法,可以實現同樣的結果。
方法二:
SELECT emp
FROM EmpSkills
WHERE skill in (SELECT skill FROM Skills)
GROUP BY emp
HAVING COUNT(DISTINCT skill)=(SELECT COUNT(skill) FROM Skills);