外聯接。外聯接可以是左向外聯接、右向外聯接或完整外部聯接。
在 FROM 子句中指定外聯接時,可以由下列幾組關鍵字中的一組指定:
LEFT JOIN 或 LEFT OUTER JOIN。
左向外聯接的結果集包括 LEFT OUTER 子句中指定的左表的所有行,而不僅僅是聯接列所匹配的行。如果左表的某行在右表中沒有匹配行,則在相關聯的結果集行中右表的所有選擇列表列均為空值。
RIGHT JOIN 或 RIGHT OUTER JOIN。
右向外聯接是左向外聯接的反向聯接。將返回右表的所有行。如果右表的某行在左表中沒有匹配行,則將為左表返回空值。
FULL JOIN 或 FULL OUTER JOIN。
完整外部聯接返回左表和右表中的所有行。當某行在另一個表中沒有匹配行時,則另一個表的選擇列表列包含空值。如果表之間有匹配行,則整個結果集行包含基表的數據值。
僅
當至少有一個同屬于兩表的行符合聯接條件時,內聯接才返回行。內聯接消除與另一個表中的任何行不匹配的行。而外聯接會返回 FROM
子句中提到的至少一個表或視圖的所有行,只要這些行符合任何 WHERE 或 HAVING
搜索條件。將檢索通過左向外聯接引用的左表的所有行,以及通過右向外聯接引用的右表的所有行。完整外部聯接中兩個表的所有行都將返回。
Microsoft® SQL Server™ 2000 對在 FROM 子句中指定的外聯接使用以下 SQL-92 關鍵字:
LEFT OUTER JOIN 或 LEFT JOIN
RIGHT OUTER JOIN 或 RIGHT JOIN
FULL OUTER JOIN 或 FULL JOIN
SQL
Server 支持 SQL-92 外聯接語法,以及在 WHERE 子句中使用 *= 和 =* 運算符指定外聯接的舊式語法。由于 SQL-92
語法不容易產生歧義,而舊式 Transact-SQL 外聯接有時會產生歧義,因此建議使用 SQL-92 語法。
使用左向外聯接
假設在 city 列上聯接 authors 表和 publishers 表。結果只顯示在出版商所在城市居住的作者(本例中為 Abraham Bennet 和 Cheryl Carson)。
若要在結果中包括所有的作者,而不管出版商是否住在同一個城市,請使用 SQL-92 左向外聯接。下面是 Transact-SQL 左向外聯接的查詢和結果:
USE pubs
SELECT a.au_fname, a.au_lname, p.pub_name
FROM authors a LEFT OUTER JOIN publishers p
ON a.city = p.city
ORDER BY p.pub_name ASC, a.au_lname ASC, a.au_fname ASC
下面是結果集:
au_fname au_lname pub_name
-------------------- ------------------------------ -----------------
Reginald Blotchet-Halls NULL
Michel DeFrance NULL
Innes del Castillo NULL
Ann Dull NULL
Marjorie Green NULL
Morningstar Greene NULL
Burt Gringlesby NULL
Sheryl Hunter NULL
Livia Karsen NULL
Charlene Locksley NULL
Stearns MacFeather NULL
Heather McBadden NULL
Michael O'Leary NULL
Sylvia Panteley NULL
Albert Ringer NULL
Anne Ringer NULL
Meander Smith NULL
Dean Straight NULL
Dirk Stringer NULL
Johnson White NULL
Akiko Yokomoto NULL
Abraham Bennet Algodata Infosystems
Cheryl Carson Algodata Infosystems
(23 row(s) affected)
不管是否與 publishers 表中的 city 列匹配,LEFT OUTER JOIN 均會在結果中包含 authors 表的所有行。注意:結果中所列的大多數作者都沒有相匹配的數據,因此,這些行的 pub_name 列包含空值。
使用右向外聯接
假
設在 city 列上聯接 authors 表和 publishers 表。結果只顯示在出版商所在城市居住的作者(本例中為 Abraham
Bennet 和 Cheryl Carson)。SQL-92 右向外聯接運算符 RIGHT OUTER JOIN
指明:不管第一個表中是否有匹配的數據,結果將包含第二個表中的所有行。
若要在結果中包括所有的出版商,而不管城市中是否還有出版商居住,請使用 SQL-92 右向外聯接。下面是 Transact-SQL 右向外聯接的查詢和結果:
USE pubs
SELECT a.au_fname, a.au_lname, p.pub_name
FROM authors AS a RIGHT OUTER JOIN publishers AS p
ON a.city = p.city
ORDER BY p.pub_name ASC, a.au_lname ASC, a.au_fname ASC
下面是結果集:
au_fname au_lname pub_name
-------------------- ------------------------ --------------------
Abraham Bennet Algodata Infosystems
Cheryl Carson Algodata Infosystems
NULL NULL Binnet & Hardley
NULL NULL Five Lakes Publishing
NULL NULL GGG&G
NULL NULL Lucerne Publishing
NULL NULL New Moon Books
NULL NULL Ramona Publishers
NULL NULL Scootney Books
(9 row(s) affected)
使用謂詞(如將聯接與常量比較)可以進一步限制外聯接。下例包含相同的右向外聯接,但消除銷售量低于 50 本的書籍的書名:
USE pubs
SELECT s.stor_id, s.qty, t.title
FROM sales s RIGHT OUTER JOIN titles t
ON s.title_id = t.title_id
AND s.qty > 50
ORDER BY s.stor_id ASC
下面是結果集:
stor_id qty title
------- ------ ---------------------------------------------------------
(null) (null) But Is It User Friendly?
(null) (null) Computer Phobic AND Non-Phobic Individuals: Behavior
Variations
(null) (null) Cooking with Computers: Surreptitious Balance Sheets
(null) (null) Emotional Security: A New Algorithm
(null) (null) Fifty Years in Buckingham Palace Kitchens
7066 75 Is Anger the Enemy?
(null) (null) Life Without Fear
(null) (null) Net Etiquette
(null) (null) Onions, Leeks, and Garlic: Cooking Secrets of the
Mediterranean
(null) (null) Prolonged Data Deprivation: Four Case Studies
(null) (null) Secrets of Silicon Valley
(null) (null) Silicon Valley Gastronomic Treats
(null) (null) Straight Talk About Computers
(null) (null) Sushi, Anyone?
(null) (null) The Busy Executive's Database Guide
(null) (null) The Gourmet Microwave
(null) (null) The Psychology of Computer Cooking
(null) (null) You Can Combat Computer Stress!
(18 row(s) affected)
有關謂詞的更多信息,請參見 WHERE。
使用完整外部聯接
若
要通過在聯接結果中包括不匹配的行保留不匹配信息,請使用完整外部聯接。Microsoft® SQL Server™ 2000
提供完整外部聯接運算符 FULL OUTER JOIN,不管另一個表是否有匹配的值,此運算符都包括兩個表中的所有行。
假設在
city 列上聯接 authors 表和 publishers 表。結果只顯示在出版商所在城市居住的作者(本例中為 Abraham
Bennet 和 Cheryl Carson)。SQL-92 FULL OUTER JOIN
運算符指明:不管表中是否有匹配的數據,結果將包括兩個表中的所有行。
若要在結果中包括所有作者和出版商,而不管城市中是否有出版商或者出版商是否住在同一個城市,請使用完整外部聯接。下面是 Transact-SQL 完整外部聯接的查詢和結果:
USE pubs
SELECT a.au_fname, a.au_lname, p.pub_name
FROM authors a FULL OUTER JOIN publishers p
ON a.city = p.city
ORDER BY p.pub_name ASC, a.au_lname ASC, a.au_fname ASC
下面是結果集:
au_fname au_lname pub_name
-------------------- ---------------------------- --------------------
Reginald Blotchet-Halls NULL
Michel DeFrance NULL
Innes del Castillo NULL
Ann Dull NULL
Marjorie Green NULL
Morningstar Greene NULL
Burt Gringlesby NULL
Sheryl Hunter NULL
Livia Karsen NULL
Charlene Locksley NULL
Stearns MacFeather NULL
Heather McBadden NULL
Michael O'Leary NULL
Sylvia Panteley NULL
Albert Ringer NULL
Anne Ringer NULL
Meander Smith NULL
Dean Straight NULL
Dirk Stringer NULL
Johnson White NULL
Akiko Yokomoto NULL
Abraham Bennet Algodata Infosystems
Cheryl Carson Algodata Infosystems
NULL NULL Binnet & Hardley
NULL NULL Five Lakes Publishing
NULL NULL GGG&G
NULL NULL Lucerne Publishing
NULL NULL New Moon Books
NULL NULL Ramona Publishers
NULL NULL Scootney Books
(30 row(s) affected)
在我敘述 JOIN 的用法前,我先引用數據庫設計中最常見的范式資料。
第三范式( 3NF ):如果關系模式 R ( U , F )中的所有非主屬性對任何候選關鍵字都不存在傳遞信賴,則稱關系 R 是屬于第三范式的。
例:如 S1 ( SNO , SNAME , DNO , DNAME , LOCATION ) 各屬性分別代表學號,姓名,所在系,系名稱,系地址。
關鍵字 SNO 決定各個屬性。由于是單個關鍵字,沒有部分依賴的問題,肯定是 2NF 。但這關系肯定有大量的冗余,有關學生所在的幾個屬性 DNO , DNAME , LOCATION 將重復存儲,插入,刪除和修改時也將產生類似以上例的情況。
原因:關系中存在傳遞依賴造成的。由于 SNAME 和 DNO 是依賴 SNO ,而 DNAME 和 LOCATION 是依賴 DNO 的,即通過一個學號可以知道該學生的姓名以及他所在系代碼,但無法由學號知道系地址,學號和系地址間是通過學號所對應的學生的所在系關聯的, 因此關鍵字 SNO 對 LOCATION 函數決定是通過傳遞依賴 DNO -> LOCATION 實現的。也就是說, SNO 不直接決定非主屬性 LOCATION 。
解決目地:每個關系模式中不能留有傳遞依賴。
解決方法:分為兩個關系 S ( SNO , SNAME , DNO ), D ( DNO , DNAME , LOCATION )
注意:關系 S 中不能沒有外關鍵字 DNO 。否則兩個關系之間失去聯系。
在數據庫的設計過程中常常按照第三范式來設計數據庫,當然在有些場合為優化數據庫的性能而增加了相關冗余字段以使表的結構不符合 3NF ,在多數場合中,沒有一張表能完整的發揮客戶所需要的結果集。這樣就需要通過聯接多張在邏輯上存在依賴關系的表,選擇你所需要的數據。
在使用 JOIN 前,必須明白是通過聯接,根據各個表之間的邏輯關系從相關表中檢索數據。通過 SQL Server 自帶幫助文件,可以清楚的知道:可在 FROM 或 WHERE 子句中指定聯接。
1.1. 在 WHERE 子句中指定聯接
下例使用 WHERE 子句進行表之間的
SELECT A.SYMBOL,A.SNAME,B.TDATE,B.CLOSE
FROM SECURITYCODE A,DAYQUOTE B
WHERE A.SYMBOL =B.SYMBOL
AND B.TDATE >= A.LISTDATE
AND A.SYMBOL LIKE '600%'
在上例中聯接的表 A 與表 B 通過 A.SYMBOL =B.SYMBOL 這個條件聯接,篩選條件為 B.TDATE 不小于 A. LISTDATE 。
在 WHERE 子句中指定聯接,對于較簡單的聯接,使用這種方式可能較方便,但綜合來說,不推薦使用該語法聯接表。
1.2. 在 FROM 子句中指定聯接
拿上面的例子來詳細說,表 SECURITYCODE 中主要存放證券代碼的基本信息,表中的 SYMBOL 代表股票代碼, SNAME 代表股票名稱, LISTDATE 代表上市日期;表 DAYQUOTE 中主要存放股票的每日行情。 SYMBOL 代表股票代碼, TDATE 代表交易日期, CLOSE 代表收盤價。
我現在的取值邏輯是:取出股票代碼以 600 打頭的股票自上市日期以來的所有交易日的收盤價。將 SECURITYCODE 與 DAYQUOTE 通過 SYMBOL 聯接。
SELECT A.SYMBOL,A.SNAME,B.TDATE,B. CLOSE
FROM SECURITYCODE A
JOIN DAYQUOTE B
ON A.SYMBOL =B.SYMBOL
WHERE B.TDATE >= A.LISTDATE
AND A.SYMBOL LIKE '600%'
ORDER BY A.SYMBOL,B.TDATE
對于使用 FROM 子句方式聯接表,可以很清楚的看出表之間的聯接條件。就可讀性以及后續的可修改性與 WHERE 子句相比有較大的優勢。
下面就聯接的方式引用幫助文件中的具體介紹,聯接可以分為以下幾種:
1.3. 內聯接
內聯接(典型的聯接運算,使用像 = 或 <> 之類的比較運算符)。包括相等聯接和自然聯接。
內聯接使用比較運算符根據每個表共有的列的值匹配兩個表中的行。
在 SQL-92 標準中,內聯接可在 FROM 或 WHERE 子句中指定。這是 WHERE 子句中唯一一種 SQL-92 支持的聯接類型。 WHERE 子句中指定的內聯接稱為舊式內聯接。
內聯接一般常見寫法:
SELECT A.COLUMN1,[A.COLUMN2],B.COLUMN1,[B.COLUMN2]
FROM TABLE1 A
[INNER] JOIN TABLE2 B
ON A.COLUMN0 = B.COLUMN0
在查詢分析器中使用 INNER JOIN 時常常省略 INNER 。
1.4. 外聯接
外聯接可以是左向外聯接、右向外聯接或完整外部聯接。
在 FROM 子句中指定外聯接時,可以由下列幾組關鍵字中的一組指定:
LEFT JOIN 或 LEFT OUTER JOIN
左向外聯接的結果集包括 LEFT OUTER 子句中指定的左表的所有行,而不僅僅是聯接列所匹配的行。如果左表的某行在右表中沒有匹配行,則在相關聯的結果集行中右表的所有選擇列表列均為空值。
RIGHT JOIN 或 RIGHT OUTER JOIN
右向外聯接是左向外聯接的反向聯接。將返回右表的所有行。如果右表的某行在左表中沒有匹配行,則將為左表返回空值。
FULL JOIN 或 FULL OUTER JOIN
完整外部聯接返回左表和右表中的所有行。當某行在另一個表中沒有匹配行時,則另一個表的選擇列表列包含空值。如果表之間有匹配行,則整個結果集行包含基表的數據值。
僅當至少有一個同屬于兩表的行符合聯接條件時,內聯接才返回行。內聯接消除與另一個表中的任何行不匹配的行。而外聯接會返回 FROM 子句中提到的至少一個表或視圖的所有行,只要這些行符合任何 WHERE 或 HAVING 搜索條件。將檢索通過左向外聯接引用的左表的所有行,以及通過右向外聯接引用的右表的所有行。完整外部聯接中兩個表的所有行都將返回。
外聯接的中常見的是 LEFT JOIN ,將 LEFT JOIN 用熟已經可以解決大半問題了。
外聯接的一般寫法:
SELECT A.COLUMN1,[A.COLUMN2],B.COLUMN1,[B.COLUMN2]
FROM TABLE1 A
LEFT|RIGHT|FULL [OUTER] JOIN TABLE2 B
ON A.COLUMN0 = B.COLUMN0
在查詢分析器中使用 OUTER JOIN 時常常省略 OUTER 。 LEFT 和 RIGHT 只是方向問題,在特定場合下, FULL OUTER JOIN 相當于 LEFT OUTER JOIN 和 RIGHT OUTER JOIN 的消除重復行的合集。
1.5. 交叉聯接
交叉聯接返回左表中的所有行,左表中的每一行與右表中的所有行組合。交叉聯接也稱作笛卡爾積。
沒有 WHERE 子句的交叉聯接將產生聯接所涉及的表的笛卡爾積。第一個表的行數乘以第二個表的行數等于笛卡爾積結果集的大小。也就是說在沒有 WHERE 子句的情況下,若表 A 有 3 行記錄,表 B 有 6 行記錄 : :
SELECT A.*,B.* FROM 表A CROSS JOIN 表B
那以上語句會返回 18 行記錄。