問題:一方關聯多方查詢時執行否認篩選,結果包含未經過篩選的項。node
咱們規定一方爲父,多方爲子,咱們但願子未經過篩選時,結果也不出現對應的父。mybatis
查詢部門及部門下的全部員工。spa
SELECT * FROM department LEFT JOIN employee ON department.id = employee.did;blog
查詢不是員工Tom所在的部門及部門下的全部員工。進階
第一想法是:SELECT * FROM department LEFT JOIN employee ON department.id = employee.did WHERE employee.name != 'Tom';im
可是結果以下,結果仍包含部門 1 ,當mybatis等處理結果時,就會爲部門 1 建立實例。這不是咱們想要的。查詢
解決1:not in 的思想(這個很慢,直接看解決2)img
not in 的思想是:先查出條件句的確定,而後外部用not in篩選。di
這裏就是,先找出有員工Tom的部門,而後篩選不是這個部門的全部部門及員工。co
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;