CHAPTER 5 Multi-table Queries
阿新 • • 發佈:2018-12-19
多表查詢
5.1 什麼是連線
5.1.1 笛卡爾積
當查詢只連線了兩個表而未指定連線列(鍵),那麼資料庫伺服器將產生笛卡爾積,即將兩個表的所有置換。
SELECT e.fname, e.lname, d.name
FROM employee e JOIN department d;
5.1.2 內連線
要修改上一個查詢就要求我們描述清楚兩個表要如何關聯的:
SELECT e.fname, e.lname, d.name
FROM employee e JOIN department d
ON e.dept_id = d.dept_id;
若存在不匹配的e.dept_id或d.dept_id,則資料庫會將其排除,這樣的連線方式也就被稱為內連線
但是對於那些未匹配的僱員行或者部門資訊,若想包含,需要使用外連線。
在上述例子中,from語句並未指定所使用的連線型別,預設為內連線,實際上,最好在from子式中顯式的指定連線型別。如:
SELECT e.fname, e.lname, d.name
FROM employee e INNER JOIN department d
ON e.dept_id = d.dept_id;#由於列名相同,可以用USING(dept_id)代替。
5.1.3 ANSI連線語法
基本所有主流的資料庫管理系統都採用了SQL92的連線語法。(這就包含了一些就的連線語法)
- 連線條件和過濾條件被分隔到兩個字句,(on子句和where子句),是查詢語句更易於理解;
- 每兩個表之間的連線條件都在他們自己的on子句中列出,這樣不容易錯誤地忽略了某些連線條件。
- 使用SQL92連線語法的查詢語句可以在各種資料管理系統通用。
SELECT a.account_id,a.cust_id,a.open_date,a.product_cd
FROM account a, branch b,employee e
WHERE a.open_emp_id = e.emp_id
AND e.start_date<'2007-01-01'
AND e.assigned_branch_id = b.branch_id
AND (e.title = 'Teller' OR e.title ='Head Teller')
AND b.name='Woburn Branch';
該查詢一方面不太容易識別where中哪些條件是連線條件,哪些是過濾條件;另一方面是對於使用了何種連線型別也並非顯而易見。(內連線還是其他)
SQL92的處理應該如下:
SELECT a.account_id,a.cust_id,a.open_date,a.product_cd
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';
這樣就顯然有連線條件都處在on語句中,過濾條件都處在where語句中。
5.2 連線3個或更多的表
參見上面,注意其中from中進行連線的表出現的次序可以任意調換,這是因為SQL是一個非過程化的語言。all you need to do is describe the object you need clearly, how to achieve it perfectly is just the databases server’s business.
5.2.1 將子查詢結果作為查詢表
SELECT a.account_id,a.cust_id,a.open_date,a.product_cd
FROM account a INNER JOIN
(SELECT emp_id,assigned_branch_id
FROM employee
WHERE start_date<'2007-01-01'
AND (title = 'Teller' OR title ='Head Teller')) e
ON a.open_emp_id = e.emp_id
INNER JOIN
(SELECT branch_id
FROM branch
WHERE b.name='Woburn Branch') b
ON e.assigned_branch_id = b.branch_id
5.2.2 連續兩次使用同一張表
若某表同時包含其他兩表的外來鍵,就需要在from子句中兩次引用該表。並最好兩次給該表不同的別名。示例如下:
SELECT a.account_id, e.emp_id, b_a.name open_branch, b_e.name emp_branch
FROM account a INNER JOIN branch b_a
ON a.open_branch_id = b_a.branch_id
INNER JOIN employee e
ON a.open_emp_id = e.emp_id
INNER JOIN branch b_e
ON e.assigned_branch_id = b_e.branch_id
WHERE a.product_cd = 'CHK';
5.3 自連線
若一個表包含了一個紙箱自身的外來鍵,即只想本表主鍵的列,如僱員表中上級領導id指向了本表中某些職位較高的employee_id,這時候就需要我們使用自連線。
SELECT e.fname, e.lname
e_mgr.fname mgr_lname, e_mgr.lname mgr_lname
FROM employee e INNER JOIN employee e_mgr
ON e.superior_emp_id = e_mgr.emp_id;
5.4 相等連線和不等連線
大多數查詢使用的是相等連線,但有時也可以通過限定值的範圍實現對錶的連線,亦稱為不等連線。有時還需要使用不等自連線。
如從僱員中安排出納員們兩兩競爭:
SELECT e1.fname, e1.lname,'VS' vs,e2.fname, e2.lname
FROM employee e1 INNER JOIN employee e2
ON e1.emp_id < e2.emp_id
WHERE e1.title = 'Teller' AND e2.title = 'Teller';
5.5 連線條件和過濾條件
最好在合適的位置放置查詢條件。