sql一關聯多查詢時否定篩選出現的問題的解決

ming_question發表於2019-06-28

問題:一方關聯多方查詢時執行否定篩選,結果包含未通過篩選的項。

我們規定一方為父,多方為子,我們希望子未通過篩選時,結果也不出現對應的父。

 

查詢部門及部門下的所有員工。

SELECT * FROM department LEFT JOIN employee ON department.id = employee.did;

查詢不是員工Tom所在的部門及部門下的所有員工。

第一想法是:SELECT * FROM department LEFT JOIN employee ON department.id = employee.did WHERE employee.name != 'Tom';

但是結果如下,結果仍包含部門 1 ,當mybatis等處理結果時,就會為部門 1 建立例項。這不是我們想要的。

解決1:not in 的思想(這個很慢,直接看解決2)

not in 的思想是:先查出條件句的肯定,然後外部用not in篩選。

這裡就是,先找出有員工Tom的部門,然後篩選不是這個部門的所有部門及員工。

SELECT *  FROM department LEFT JOIN employee ON department.id = employee.did WHERE department.id

NOT IN (SELECT department.id FROM department LEFT JOIN employee ON department.id = employee.did WHERE employee.name = 'Tom');

NOT IN 篩選ID的時候使用最後一個一方的ID,會更快一點。

例如:A  多對一  B  一對一  C  多對一  D  多對多  E

這個時候一直到 D 都是一方 所以 NOT IN 時使用 D 的欄位篩選。即...WHERE D.COLUMN NOT IN (SELECT D.COLUMN FROM...

解決2:not in 的思想進階

使用LEFT JOIN 代替 NOT IN。

將NOT IN 的子查詢當做一個表,對其進行關聯,然後篩選這個表欄位為空的。

例如還是這個例子

SELECT department.id FROM department LEFT JOIN employee ON department.id = employee.did WHERE employee.name = 'Tom';

我們設這個表為 nodepartment 列為 id。結果應該只有一行一列 ‘1’。

則主表關聯nodepartment後  department.id 為 2 的行 nodepartment.id這一列為null。所以主表條件 nodepartment.id IS NULL就可以了。

在這裡就是:

SELECT *  FROM department LEFT JOIN employee ON department.id = employee.did

LEFT JOIN 

 (SELECT department.id AS nodepid FROM department LEFT JOIN employee ON department.id = employee.did

WHERE employee.name = 'Tom')  AS nodep ON department.id = nodep.nodepid

WHERE nodepid IS NULL;

相關文章