程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 1. SQL讀書筆記——SQL中的連接(1),sql讀書筆記

1. SQL讀書筆記——SQL中的連接(1),sql讀書筆記

編輯:MySQL綜合教程

1. SQL讀書筆記——SQL中的連接(1),sql讀書筆記


 

《SQL學習指南》中的第5章    1.連接:      在某種機制下,需要將多個表中的數據進行整合到一起,即同一個查詢的結果集中包含來自兩個或者兩個以上的表,這種機制被稱為連接(join).    1.1 ANSI連接語法      本文采用的都是符合SQL92版本的ANSI SQL標准,所有的主流數據庫都采用了SQL92的連接語法。由於這些數據庫都出現SQL92標准發布之前,同時存在一些舊的連接語法,如下所示:      例子1:      SELECT e.fname, e.lname, d.`name`      FROM employee e , department d      WHERE e.dept_id = d.dept_id;          推薦使用SQL92標准 的連接方式,不推薦使用上面的連接方式,主要原因是:      1)連接條件和過濾條件被分隔到兩個子句中(ON子句和WHERE子句),使得查詢語句更利於理解;      2)每兩個表的連接條件都在ON子句中列出,容易找出連接條件;      3)SQL92標准可以在各種數據庫中通用,而舊的語法在不同的數據中的表現可能略有不同; 
         1.2 笛卡爾積      例子 1: 直接使用from連接employee 和 department表      方式一:      SELECT e.fname, e.lname, d.`name`      FROM employee e JOIN department             一個有18個雇員和3個部門,會產生54行數據,由於查詢沒有明確的指定兩個表是如何連接的造成的,這時會默認兩張表置換。這樣的連接被稱為交叉連接(cross join).  1.3 內連接            1)兩表連接      例子1: 查詢每個雇員所屬的部門信息        SELECT e.fname, e.lname, d.`name`      FROM employee e JOIN department d           ON e.dept_id = d.dept_id            結果如圖所示
     

 

           此時通過描述上面兩個表是通過何種方式關聯的,是通過dept_id來關聯兩個表的。      如果在一個表中的dept_id列中存在某個值,但該值在另一張表的dept_id列中不存在,那麼此時相關的行的連接會失敗,在結果集中的相關行的連接會失敗,在結果集中將會排除包含該值的行,這種類型的連接被稱為內連接     若想要包含某個表中的所有行,並不需要考慮該表的每一行都與另一張表匹配,那麼可以使用外連接       2)多表內連接      -- 例子2.查詢Woburn支行中所有熟練櫃員(在2007年以前入職的櫃員)開設的賬戶   SELECT a.account_id, a.product_cd,a.open_date FROM account a INNER JOIN employee e ON a.open_emp_id = e.emp_id INNER JOIN branch b ON e.assigned_branch_id = b.branch_id WHERE e.start_date < '2007-01-01' AND (e.title = 'Teller' OR e.title = 'Head Teller') AND b.`name` = 'Woburn Branch';   結果如圖所示:

 

     現在FROM子句中包含3個表,兩種連接類型和兩個ON子句,看上去連接的順序是account表,employee表,然後branch表,那麼如果交換employ表和account表的連接順序會出現什麼情況呢?       SELECT a.account_id, a.product_cd,a.open_date FROM employee e INNER JOIN account a ON a.open_emp_id = e.emp_id INNER JOIN branch b ON e.assigned_branch_id = b.branch_id WHERE e.start_date < '2007-01-01' AND (e.title = 'Teller' OR e.title = 'Head Teller') AND b.`name` = 'Woburn Branch';   結果如圖所示---無改變 那麼在更換employee和branch的順序呢?   SELECT a.account_id, a.product_cd,a.open_date FROM branch b INNER JOIN account a ON a.open_branch_id = b.branch_id INNER JOIN employee e ON a.open_emp_id = e.emp_id WHERE e.start_date < '2007-01-01' AND (e.title = 'Teller' OR e.title = 'Head Teller') AND b.`name` = 'Woburn Branch';   結果如圖所示---無改變   那麼更換ON語句的位置呢   SELECT a.account_id, a.product_cd,a.open_date FROM branch b INNER JOIN account a INNER JOIN employee e ON a.open_branch_id = b.branch_id ON a.open_emp_id = e.emp_id WHERE e.start_date < '2007-01-01' AND (e.title = 'Teller' OR e.title = 'Head Teller') AND b.`name` = 'Woburn Branch';   結果如圖所示---報錯!錯誤原因:ON語句連接關系要緊跟 JOIN語句      例子二多種表達方式的原因:SQL是一種非過程化的語言,也就是說只需要描述要獲取的數據對象, 而執行過程是數據庫服務器負責(我只要結果集*_*)(但是左連接,右連接的問題,還不是很確定,稍後還要進行測試一下)   3)子查詢作為結果集的內連接 例子二中的另一個版本:使用“連接 ”連接子查詢,也就是將子查詢的結果集作為查詢表進行連接   1)       SELECT e.emp_id FROM employee e WHERE e.start_date < '2007-01-01' AND (e.title = 'Teller' OR e.title = 'Head Teller');   2)  SELECT b.branch_id FROM  branch b WHERE b.`name` = 'Woburn Branch';   3)  SELECT a.account_id, a.product_cd,a.open_date FROM account a INNER JOIN (SELECT e.emp_id FROM employee e WHERE e.start_date < '2007-01-01' AND (e.title = 'Teller' OR e.title = 'Head Teller') ) em ON a.open_emp_id = em.emp_id INNER JOIN (SELECT b.branch_id FROM  branch b WHERE b.`name` = 'Woburn Branch') br ON a.open_branch_id = br.branch_id;   4)自連接 例子3.列出雇員的姓名同時列出主管的姓名:   SELECT emp.emp_id AS emp_id,CONCAT(emp.fname,' ',emp.lname) AS em, e.emp_id AS super_em_id,CONCAT(e.fname,' ',e.lname) AS super_em FROM employee e INNER JOIN employee emp ON e.emp_id = emp.superior_emp_id;   結果如圖所示:          上面查詢實現了對表自身進行連接,自連接,employee表中包含了指向自身的外鍵(superior_emp_id) 同時,employee表一共18行,但此查詢返回了17行,這是由於銀行的總經理MIchael Smith並沒 自己的主管,它的superior_emp_id列為null,因此在改行上的內連接失敗,在結果集中並不會顯示。   5)不等連接 例子4.假如執行經理決定舉辦一次面向銀行櫃員的象棋比賽,現在要創建所有對弈者的列表      SELECT CONCAT(e.fname,' ',e.lname) as TEAM_A, 'VS', CONCAT(emp.fname,' ',emp.lname) as TEAM_B FROM employee e INNER JOIN employee emp ON e.emp_id < emp.emp_id WHERE e.title = 'Teller' AND emp.title = 'Teller'; 結果如圖所示:  

 

                         

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved