1.1.1 摘要
Join是關系型數據庫系統的重要操作之一,SQL Server中包含的常用Join:內聯接、外聯接和交叉聯接等。如果我們想在兩個或以上的表獲取其中從一個表中的行與另一個表中的行匹配的數據,這時我們應該考慮使用Join,因為Join具體聯接表或函數進行查詢的特性
本文將通過具體例子介紹SQL中的各種常用Join的特性和使用場合:
1.1.2 正文
首先我們在tempdb中分別定義三個表College、Student和Apply,具體SQL代碼如下:
復制代碼 代碼如下:
USE tempdb
---- If database exists the same name datatable deletes it.
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'College') DROP TABLE College;
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Student') DROP TABLE Student;
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Apply') DROP TABLE Apply;
---- Create Database.
create table College(cName nvarchar(50), state text, enrollment int);
create table Student(sID int, sName nvarchar(50), GPA real, sizeHS int);
create table Apply(sID int, cName nvarchar(50), major nvarchar(50), decision text);
Inner join
內聯接(Inner join)是最常用的聯接類型之一,它查詢滿足聯接謂詞的數據。
假設我們要查詢申請表Apply中申請學校的相關信息,由于Apply表中包含學校名字我們并不能預知,所以我們可以根據cName來內聯接(Inner join)表College和Apply,從而找到Apply表中包含學校的信息。
具體SQL代碼如下:
復制代碼 代碼如下:
---- Gets college information from college table
---- bases on college name.
SELECT DISTINCT College.cName, College.enrollment
FROM College INNER JOIN
Apply ON College.cName = Apply.cName
![SQL Join的一些總結(實例) SQL Join的一些總結(實例)]()
圖3左聯接查詢結果
如上圖3所示:由于在Apply表中并沒有學生申請Harvard,但是我們通過左聯接(left outer join)把所有學校信息查詢出來了。
由于左聯接(left outer join)產生表College的完全集,而Apply表中匹配的則有值,而不匹配的則以NULL值取代,所以我們知道Apply表中沒有學生申請Harvard。
通過左聯接查詢我們可以獲取College的完全集,假設現在我們既要獲取College的完全集又要獲取Apply的完全集,那么我們可以考慮使用完整外部聯接(full outer join)。使用完整外部聯接,我們可以查詢所有的學校,不管它們是否匹配聯接謂詞:
復制代碼 代碼如下:
---- Gets all information from college and apply table.
SELECT College.cName, College.state, College.enrollment,
Apply.cName, Apply.major, Apply.decision
FROM College FULL OUTER JOIN
Apply ON College.cName = Apply.cName
![SQL Join的一些總結(實例) SQL Join的一些總結(實例)]()
圖4 College表和Apply表的行數
![SQL Join的一些總結(實例) SQL Join的一些總結(實例)]()
圖6 Cross apply查詢
Outer apply
在介紹Cross apply和Outer join之后,現在讓我們理解Out apply也就不難了,Outer apply使表可以和表值函數(table-valued functions TVF‘s)結果進行join查詢,找到匹配值則有值,沒有找到匹配值則以NULL表示。
復制代碼 代碼如下:
---- Student outer apply function fn_Apply.
SELECT Student.sName, Student.GPA, Student.sizeHS,
cName, major
FROM Student OUTER APPLY dbo.fn_Apply([sID])
![SQL Join的一些總結(實例) SQL Join的一些總結(實例)]()
圖8 執行計劃
如圖8所示:Cross apply首先執行TVF(table-valued functions),然后對表Studnet進行全表掃描,接著通過遍歷sID查找匹配值。
Inner join對表Student和Apply進行全表掃描,然后通過哈希匹配查找匹配的sID值。
通過以上的SQL執行時間和執行計劃,我們能不能說Inner join比Cross apply好呢?答案是否定的,如果表的數據量很大,那么Inner join的全表掃描耗費時間和CPU資源就增加了(可通過數據量大的表進行測試)。
雖然大多數采用Cross apply實現的查詢,可以通過Inner join實現,但Cross apply可能產生更好的執行計劃和更佳的性能,因為它可以在聯接執行之前限制集合加入。
Semi-join和Anti-semi-join
Semi-join從一個表中返回的行與另一個表中數據行進行不完全聯接查詢(查找到匹配的數據行就返回,不再繼續查找)。
Anti-semi-join從一個表中返回的行與另一個表中數據行進行不完全聯接查詢,然后返回不匹配的數據。
不同于其他的聯接運算,Semi-join和Anti-semi-join沒有明確的語法來實現,但Semi-join和Anti-semi-join在SQL Server中有多種應用場合。我們可以使用EXISTS子來實現Semi-join查詢,Not EXISTS來實現Anti-semi-join?,F在讓我們通過具體的例子說明吧!
假設要求我們找出Apply和Student表中sID匹配的學生信息,這和前面的Inner join查詢結果將一樣,具體SQL代碼如下:
復制代碼 代碼如下: