1. 程式人生 > >多表連線查詢(內,外,交叉連線)

多表連線查詢(內,外,交叉連線)

連線查詢實際上是通過各個表之間共同列的關聯性來查詢資料的,它是關係資料庫查詢最主要的特徵.
select 
1.欄位名1,表2.欄位名2... 
from 
1,表2
where 
連線條件
SQL-92
標準所定義的FROM子句的連線語法格式為: 
FROM 
表名 join_type 表名 [ON (連線條件)]
連線操作中的ON (連線條件子句指出連線條件,它由被連線表中的列和比較運算子、邏輯運算子等構成。連線查詢分類:
1.
自連線查詢,對同一個表進行連線操作(可以理解為兩個不同表的內連線,有時可與巢狀查詢等價)2.內連線查詢,<又分為:自然連線、等值連線、不等值連線三種>
3.

外連線查詢,<又分為:左外連線、右外連線、全外連線三種>
4.
交叉連線查詢,也作無條件查詢。
5.
聯合查詢

一.自連線查詢:

一個表自己與自己建立連線稱為自連線或自身連線。進行自連線就如同兩個分開的表一樣,可以把一個表的某一行與同一表中的另一行連線起來。例:查詢選學“101”課程的成績高於“9505201”號學生成績的所有學生記錄,並按成績從高到低排列。
select x.* from sclass x,sclass y
where x.cno=''101'' and x.degree>y.degree and y.sno=''9505201'' and y.cno=''101''
order by x.degree desc

內連線查詢

內連線(INNER JOIN)使用比較運算子進行表間某()列資料的比較操作,並列出這些表中與連線條件相匹配的資料行。根據所使用的比較方式不同,內連線又分為等值連線、自然連線和不等連線三種。

1、等值連線:所謂等值連線,是指表之間通過等於關係連線起來,產生一個臨時表,然後對該臨時表進行處理後生成最終結果。其查詢結果中列出被連線表中的所有列,包括其中的重複列

SELECT * 
FROM authors AS a INNER JOIN publishers AS p 
ON a.city=p.city

我們可以有兩種方式,這兩種是等效的一種是:SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e,DeptTB AS d WHERE e.deptid=d.deptid 

另外一個是:SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e INNER JOIN DeptTB AS d ON e.deptid=d.deptid 

3、自然連線:在等值連線中消除重複列就是自然連線。(state,city在兩個表中都存在)

SELECT a.*,p.pub_id,p.pub_name,p.country 
FROM authors AS a INNER JOIN publishers AS p 
ON a.city=p.city

 外連線查詢 (左外連線、右外連線、全外連線)

左向外聯接的結果集包括 LEFT OUTER 子句中指定的左表的所有行,而不僅僅是聯接列所匹配的行。如果左表的某行在右表中沒有匹配行,則在相關聯的結果集行中右表的所有選擇列表列均為空值

右向外聯接是左向外聯接的反向聯接。將返回右表的所有行。如果右表的某行在左表中沒有匹配行,則將為左表返回空值。

A left join B 的連線的記錄數與A表的記錄數同
A right join B 的連線的記錄數與B表的記錄數同  這種說法是錯誤的,只有當表A與表B是一對一時才成立。

首先我們做兩張表:員工資訊表和部門資訊表,在此,表的建立只為講述連線的概念,所以欄位非常的簡單 
EmployeeTB
(員工資訊表): 

employeeid employeename deptid 
0001  
張三  01 
0002  
李四  01 
0003  
王五  02 
0004  
趙六  02 
0005  
鄭七  NULL 

DeptTB
(部門資訊表) 
deptid  deptname 
01  
技術部 
02  
市場部 
03  
工程部 

1左外聯結但是有些情況下,我們需要知道所有員工的資訊,即使他不屬於任何部門。這樣我們就可以採用外連線,在這裡為左外連線,也就是連線中的左表的表中的記錄,無論能不能在右表中找到匹配的項,都要檢索,如果沒有匹配的專案,那麼右表中的欄位值為NULL(空),在這裡就代表,此員工不屬於任何部門。檢索語句為: 
SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e LEFT OUTER JOIN DeptTB AS d ON e.deptid=d.deptid 
檢索的結果都是: 

employeeid employeename deptname 
0001  
張三 技術部 
0002  
李四 技術部 
0003  
王五 市場部 
0004  
趙六 市場部 
0005  
鄭七  NULL 

但是在這裡,工程部同樣不會被檢索,因為,deptname是在連線的右邊的表中,工程部在左表中不存在任何的記錄,所以不會被檢索。這裡關注的是連線中的左邊的表” 


2
、右外連線有時,我們需要知道,全部部門的資訊,即使它沒有任何的員工。在我們的查詢中部門表在連線的右邊,如果我們想知道右邊表中的所有記錄資訊,那麼就可以採用右外連線,如果此記錄在左邊的表中找不到匹配項,則相應欄位(employeeid,employeename)NULL 
檢索語句為: 
SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e RIGHT OUTER JOIN DeptTB AS d ON e.deptid=d.deptid 
檢索的結果都是: 

employeeid employeename deptname 
0001  
張三 技術部 
0002  
李四 技術部 
0003  
王五 市場部 
0004  
趙六 市場部 
NULL  NULL  
工程部但在這裡,鄭七是不會被檢索了,因為它在右表中找不到匹配項,這裡關注的是連線中的右邊的表” 

3
、完全外連線如果我們想知道所有的記錄呢?無論員工有沒有部門,部門有沒有員工,我們都需要檢索。這裡就可以使用完全外連線。關注連線中的兩部分。如果沒有部門,部門為空,沒有員工,員工資訊為空。檢索語句為: 
SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e FULL OUTER JOIN DeptTB AS d ON e.deptid=d.deptid 
檢索的結果都是: 

employeeid employeename deptname 
0001  
張三 技術部 
0002  
李四 技術部 
0003  
王五 市場部 
0004  
趙六 市場部 
0005  
鄭七  NULL 
NULL  NULL  
工程部 

四.交叉連線交叉連線不帶WHERE 子句,它返回被連線的兩個表所有資料行的笛卡爾積,返回到結果集合中的數據行數等於第一個表中符合查詢條件的資料行數乘以第二個表中符合查詢條件的資料行數。例,titles表中有6類圖書,而publishers表中有8家出版社,則下列交叉連線檢索到的記錄數將等6*8=48行。

三個表的左連線示例:

準備資料:


表t1 
欄位名:t1_id,username,psw 
表t2 
欄位名:t2_id,gname,t1_id //這裡一個t1_id對應多個t2_id 
t3 
欄位名:t3_id,realname,tel,t1_id //這裡一個t1_id對應一個t3_id

複製程式碼  DROP TABLE [t1] 
 CREATE TABLE [t1] (  [t1id] [int] NULL , [username] [varchar] (
50) NULL , [psw] [varchar] (50) NULL )

 INSERT [t1] ( [t1id] , [username] , [psw] ) VALUES ( 
1 , 'username1' , 'psw1' )
 INSERT [t1] ( [t1id] , [username] , [psw] ) VALUES ( 
2 , 'username2' , 'psw2' )
 INSERT [t1] ( [t1id] , [username] , [psw] ) VALUES ( 
3 , 'username3' , 'psw3' )

 DROP TABLE [t2] 
 CREATE TABLE [t2] (  [t2id] [int] NULL , [gname] [varchar] (
50) NULL ,  [t1id] [int] NULL )

 INSERT [t2] ( [t2id] , [gname] , [t1id] ) VALUES ( 
1 , 'ganme1' , 1 )
 INSERT [t2] ( [t2id] , [gname] , [t1id] ) VALUES ( 
2 , 'ganme2' , 1 )
 INSERT [t2] ( [t2id] , [gname] , [t1id] ) VALUES ( 
3 , 'ganme3' , 2 )
 INSERT [t2] ( [t2id] , [gname] , [t1id] ) VALUES ( 
4 , 'ganme4' , 2 )
 INSERT [t2] ( [t2id] ) VALUES ( 
5 )

 DROP TABLE [t3] 
 CREATE TABLE [t3] (  [t3id] [int] NULL , [realname] [varchar] (
50) NULL , [tel] [varchar] (50) NULL ,  [t1id] [int] NULL )

 INSERT [t3] ( [t3id] , [realname] , [tel] , [t1id] ) VALUES ( 
1 , 'realname' , '123' , 1 )
 INSERT [t3] ( [t3id] , [realname] , [tel] , [t1id] ) VALUES ( 
3 , 'realname3' , '1234' , 3 ) 複製程式碼

遇到的麻煩是當一個realname在t2表中沒有內容時,也要將此realname的username,psw,tel等顯示出來,直接使用 
sql="select username,psw,gname,tel from t1,t2,t3 where t1.t1_id=t2.t1_id and t1.t1_id=t3.t1_id" 
得到的結果是:t2表中必須有某個realname的作品,才能查詢出來他的資訊,這肯定不是想要的結果,最後想到使用左連線,sql語句是: 
sql="select username,psw,gname,tel from (t1 left join t2 on t1.t1_id=t2.t1_id) left join t3 on t1.t1_id=t3.t1_id"

 思路:t2是資料結構中多的一表,因此先由t1與t2左連線得到最全的資料,然後再與t3連線,