《SQL學習指南》中的第10章 1.4 外連接 在多表連接中,存在連接條件可能無法表中所有的行匹配的問題,例如當account表與customer表進行連接時,會存在account表中cust_id列值無法匹配customer表中的cust_id列值,內連接在無法匹配成功時,是不會將這條匹配失敗的結果放入返回的結果集中,假如我們需要強調某個表,也就是某個表的所有行必須返回,這個表的行數決定了返回結果集的行數。 1)左外連接 關鍵詞:left outer join & left join ,left指出了連接了左邊的表決定結果集的行數,而右邊只負責提供與之匹配的列值。 例子1. 1)查詢所有的商業客戶賬戶 ——這是內連接 SELECT a.account_id ,b.cust_id,b.`name` FROM account a INNER JOIN business b ON a.cust_id = b.cust_id; 結果如圖所示:
2)查詢所有的客戶,但同時如果是商業客戶,返回其客戶名稱。
SELECT a.account_id ,a.cust_id,b.`name` FROM account a LEFT OUTER JOIN business b ON a.cust_id = b.cust_id; 結果如圖所示:3)查詢所有的客戶,但同時如果是私人客戶,返回其客戶名稱。
SELECT a.account_id ,a.cust_id, CONCAT(i.fname,' ',i.lname) AS gustname FROM account a INNER JOIN individual i ON a.cust_id = i.cust_id; 結果如圖所示:2)右外連接
關鍵詞:right outer join & rigth join ,同理right指出了連接了右的表決定結果集的行數,而左邊只負責提供與之匹配的列值。 1) SELECT c.cust_id , b.`name` FROM customer c RIGHT JOIN business b ON c.cust_id = b.cust_id; 結果如下圖所示3)多表外連接
1)獲取所有的賬戶列表,其中包含個人客戶的姓名以及商業客戶的企業名稱 SELECT a.account_id, CONCAT(i.fname,' ',i.lname) AS person_name, b.`name` as business_name FROM account a LEFT JOIN individual i ON a.cust_id = i.cust_id LEFT JOIN business b ON a.cust_id = b.cust_id ; 結果如下圖所示SELECT COUNT(*) FROM account a;
結果如下上面多表進行外連接,以account為主表,去匹配individual表中用戶,若匹配不成功,顯示為null;再去匹配business表中用戶,同理匹配不成功,顯示為null.同時說明了外連接中,存在以哪個表為主表,所以主表的順序是不可變,解決上一次筆記中的遺留問題:內連接與表的順序無關,但是外連接要注意主表所在的位置。
通過子查詢的方式實現上面的三個表同時進行的自連接: SELECT indi.id, person_name,bussiness_name FROM ( SELECT a.account_id AS id, CONCAT(i.fname,' ',i.lname) as person_name FROM account a LEFT JOIN individual i ON a.cust_id = i.cust_id ) AS indi INNER JOIN ( SELECT a.account_id AS id, b.`name` AS bussiness_name FROM account a LEFT JOIN business b ON a.cust_id = b.cust_id ) AS busi ON indi.id = busi.id; 結果如下圖所示 4)自外連接 1)前面通過內連接實現的一個問題:獲取雇員及其主管的信息 SELECT e.emp_id,CONCAT(e.fname,' ',e.lname) AS emp_name, em.emp_id AS su_emp_id,CONCAT(em.fname,' ', em.lname) AS superior_name FROM employee e INNER JOIN employee em ON e.superior_emp_id = em.emp_id; 結果如下圖所示:上面的結果由於是內連接的原因,雇員信息會缺失一條,因為總經理是最高級別職員,沒有上級,所以匹配不成功,沒有在結果集中顯示。下面通過左連接的方式,可以解決這個問題。 SELECT e.emp_id,CONCAT(e.fname,' ',e.lname) AS emp_name, em.emp_id AS su_emp_id,CONCAT(em.fname,' ', em.lname) AS superior_name FROM employee e LEFT JOIN employee em ON e.superior_emp_id = em.emp_id; 結果如下圖所示:
將上面的左連接更改成右連接,這時候就是獲取每個主管的下屬職員 SELECT e.emp_id,CONCAT(e.fname,' ',e.lname) AS emp_name, em.emp_id AS su_emp_id,CONCAT(em.fname,' ', em.lname) AS superior_name FROM employee e RIGHT JOIN employee em ON e.superior_emp_id = em.emp_id; 結果如下圖所示:
當某個主管下面存在n個職員時,這樣就會在該主管對應的數據增加n-1條數據,這也就是18個雇員,為什麼查出的結果集中有28條數據的。