create table Customers( Id int identity(1000000,1), Company varchar(30) null, Name varchar(20) null ) insert into Customers values('Fun4All','Tom') insert into Customers values('Alibaba','Tim') insert into Customers values('BaiDu','Jerry') insert into Customers values('G0ogle','Herry') insert into Customers values('Tencent','MaHuaTeng') insert into Customers values('Fun4All','Bill')
這是講解所需要的sql腳本
一、自聯結 代碼如下:
select * from Customers
現在有個需求,需要給Tom同一公司的所有會員發送一條郵件。
分析下基本思路,首先根據Tom找到其所在的公司名,在根據公司名找到其公司民下的所有會員。下面是解決代碼:
select * from Customers where Company in(select Company from Customers where Name='Tom')
ok,通過子查詢輕松的完成需求!
但是這邊有一個重點,你必須要知道,子查詢雖然方便,但是大多數DBMS的處理子查詢的速度比處理聯結要慢的多,如果數據量少的話,幾乎沒什么影響,但是如果后期數據會很大的話,就應該使用自聯結!
下面是使用自聯結的解決代碼:
select * from Customers c1,Customers c2 where c1.Company=c2.Company
這是自聯結之后的效果!
select * from Customers c1,Customers c2 where c1.Company=c2.Company and c2.Name='Tom'
這個是兩張表(實際是一張表)聯結之后的結果圖,ok完成需求!
自聯結通過聯結的機制,將所有公司名相同的記錄聯結到一起,即每一個公司的會員,都會和同一公司的其他會員聯結一次,因為他們的公司名相同,這是時候指定c2.name='Tom',就能拿到Tom和其公司所有會員的資料,這個時候就可以發郵件了!
二、自然聯結
無論何時對表進行聯結,應該至少有一列不止出現在一個表中(被聯結的列)。標准的聯結返回所有的數據,相同的列甚至出現多次。而自然聯結就是排除多次出現,是每一列只出現一次。
但是SQL不提供這項功能,自然聯結的功能是需要你自己去完成的,自然聯結要求你只能選擇哪些唯一的列,一般通過對一個表使用通配符(SELECT *),而對其他表的列使用明確的子集來完成。
注意:我們迄今為止建立的每個內聯結都是自然聯結,很可能永遠都不會用到不是自然聯結的內聯結。
三、外聯結(左外聯結(LEFT OUTER JOIN)和右外聯結(RIGHT OUTER JOIN))
許多聯結將一個表中的行與另一個表中的行相關聯,但有時候需要需要包含哪些沒有關聯的行。例如,有如下需求
(1)對每個顧客下的訂單書進行計數,包括那些至今尚未下訂單的顧客;
(2)列出所有產品以及訂購數量,包括沒有人訂購的產皮
(3)計算平均銷售規模,包括那些至今尚未下訂單的顧客;
內聯結代碼如下:
select * from Customers select * from Orders
select * from Customers a INNER JOIN Orders b ON a.Id=b.CustomerId
這邊我們使用了內聯結檢索出所有用戶的訂單,通過內聯結的檢索結果和外聯結的檢索結果比較,來更好的理解外聯結!
通過結果圖,發現內聯結確實把所有用戶的訂單都檢索出來了,但是這里內聯結似乎把沒有訂單的用戶給過濾掉了,所以我們分析得出內聯結只把有訂單的所有用戶信息包括訂單信息檢索出來,但是如果用戶沒有訂單,則該用戶信息會被過濾!
下面再來看外聯結代碼:
select * from Customers select * from Orders select * from Customers a LEFT OUTER JOIN Orders b ON a.Id=b.CustomerId
這邊我們使用了左外聯結檢索出所有用戶的訂單
通過結果圖,發現外聯結也把所有用戶的訂單都檢索出來了,但是這里外聯結把沒有訂單的用戶也檢索出來了(即外聯結能檢索出沒有關聯行的行,對應的用null來填充其關聯行),只是它的訂單信息沒有,所以對應的用null來替換,這就是外聯結和內聯結的最主要的差別,我們可以根據不同的業務需求,來選擇性的使用它們!
四、全外連接(FULL OUTER JOIN)
select * from Customers select * from Orders select * from Customers a FULL OUTER JOIN Orders b ON a.Id=b.CustomerId
分析Orders和Customers表結果圖發現:趙六和馮七沒有下訂單,而訂單表中的第四單沒有與之對應的顧客,再看全連接之后的結果圖,發現全聯結把所有沒有沒有與之對應關聯行的行全部用null填充,這就是全聯結的作用!
五、使用帶聚集函數的聯結
聚集函數是用來匯總數據,在我前面的隨筆中所用的聚集函數的例子都是從一個表中匯總數據,其實聚集函數也可以和聯結一起使用,其實聯結是多個小表組裝而成的一個大表(你可以這樣理解).
下面通過例子來了解其用法,代碼如下:
select * from Customers select * from Orders
現在有個需求,需要檢索出所有顧客的訂單數量(沒有則為0),下面是解決代碼:
select a.Id,a.Name,COUNT(b.CustomerId) from Customers a LEFT JOIN Orders b ON a.Id=b.CustomerId GROUP by a.Name,a.Id
ok,完成需求!
六、使用聯結和聯結條件(使用聯結主要注意的要點)
(1)注意所使用的聯結類型。一般我們使用內聯結(INNER JOIN)使用外聯結同樣有效! ---這一點上面'三'已論述
(2)保證使用正確的聯結條件(不管采用哪種語法、那種聯結),否則會返回不正確的數據。
(3)所有的聯結都需要提供聯結條件,否則會得出笛卡爾積。
(4)在一個聯結中可以包含多個表,甚至可以對每個聯結采用不同的聯結類型。這樣做是合法的,也是有用的,但是在一起測試它們前分別測試每個聯結。這樣會使排除故障更簡單。