1. 程式人生 > >(整理) SQL中幾種連線的相互區別

(整理) SQL中幾種連線的相互區別

連線型別定義內連線只連線匹配的行左外連線包含左邊表的全部行(不管右邊的表中是否存在與它們匹配的行),以及右邊表中全部匹配的行右外連線包含右邊表的全部行(不管左邊的表中是否存在與它們匹配的行),以及左邊表中全部匹配的行全外連線包含左、右兩個表的全部行,不管另外一邊的表中是否存在與它們匹配的行。
(H)(theta)
連線使用等值以外的條件來匹配左、右兩個表中的行交叉連線生成笛卡爾積-它不使用任何匹配或者選取條件,而是直接將一個數據源中的每個行與另一個數據源的每個行都一一匹配

舉個例子:  
  假設a表和b表的資料是這樣的。  
  a                         b    
  id     name  id     stock   
  1

  a             1         15  
  2
         b             2         50  
  3
         c                  
   
  select   *   from   a   inner   join   b   on   a.id=b.id  
  這個語法是連線查詢中的內連線,它產生的結果是  
  兩個表相匹配的記錄出現在結果列表中。  
  根據上面的表,出現的結果是這樣的  
  a.id     name     b.id     stock  
  1       a             1
         15  
  2
             b             2         50  
  ----------------------------  
  select   *   from   a,b   where   a.id=b.id  
這個語法是內連線的另外一種寫法,其執行結果與inner   join   一樣  
   
  --------------------------------    
   
  select   *   from   a   left/right   join   b   on   a.id=b.id  
  這個是外連線語法中的左外連線或右外連線  
  如果是左外連線的話,它將顯示a表的所有記錄,  
  select
   a.*,b.*   from   a   left   join   b   on   a.id=b.id  
  查詢的結果是這樣的:  
  a.id     name     b.id     stock  
  1         a         1             15  
  2
               b         2             50  
  3
               c       null         null   
  --------------------------------------------  
  如果是右外連線的話,它將顯示b表的所有記錄,  
  select   a.*,b.*   from   a   right   join   b   on   a.id=b.id  
  查詢的結果是這樣的:  
  a.id     name     b.id     stock  
  1         a         1             15  
  2
               b         2             50   


--

select   a.*,b.*   from   a   left   join   b   on   a.k   =   b.k    
  select   a.*,b.*   from   a   left   outer   join   b   on   a.k   =b.k  
  ----------上面兩種一樣left   joinleft   outer   join的簡寫  select   a.*,b.*   from   a   left   inner   join   b   on   a.k   =   b.k    
  沒有這種寫法,錯誤的語句.


--

在你要使用多個left   join的時候  
  比如說10個  
  我們把10個全都寫成left   join的形式  
  然後再SQL讓他自動執行一下,它會把最後一次出現的left   join變成left   outer   join  
  所以依此推理,最後一個left   join會以left   outer   join的形式存在  
  當然,不管變不變對結果的顯示沒有任何影響  
  希望我的實驗能對你有所幫助   


--

使用關係代數合併資料

1 關係代數


合併資料集合的理論基礎是關係代數,它是由E.F.Codd於1970年提出的。
在關係代數的形式化語言中:
        用表、或者資料集合表示關係或者實體。r
        用行表示元組。r
        用列表示屬性。r
關係代數包含以下8個關係運算符
        選取――返回滿足指定條件的行。r
        投影――從資料集合中返回指定的列。r
        笛卡爾積――是關係的乘法,它將分別來自兩個資料集合中的行以所有可能的方式進行組合。r
        並――關係的加法和減法,它可以在行的方向上合併兩個表中的資料,就像把一個表壘在另一個表之上一樣。r
        交――返回兩個資料集合所共有的行。r
        差――返回只屬於一個數據集合的行。r
        連線――在水平方向上合併兩個表,其方法是:將兩個表中在共同資料項上相互匹配的那些行合併起來。r
        除――返回兩個資料集之間的精確匹配。r
此外,作為一種實現現代關係代數運算的方法,SQL還提供了:
        子查詢――類似於連線,但更靈活;在外部查詢中,方式可以使用表示式、列表或者資料集合的地方都可以使用子查詢的結果。r
本章將主要講述多種型別的連線、簡單的和相關的子查詢、幾種型別的並、關係除以及其他的內容。

2 使用連線


2.1 連線型別
在關係代數中,連線運算是由一個笛卡爾積運算和一個選取運算構成的。首先用笛卡爾積完成對兩個資料集合的乘運算,然後對生成的結果集合進行選取運算,確保只把分別來自兩個資料集合並且具有重疊部分的行合併在一起。連線的全部意義在於在水平方向上合併兩個資料集合(通常是表),併產生一個新的結果集合,其方法是將一個數據源中的行於另一個數據源中和它匹配的行組合成一個新元組。
SQL提供了多種型別的連線方式,它們之間的區別在於:從相互交疊的不同資料集合中選擇用於連線的行時所採用的方法不同。
連線型別定義內連線只連線匹配的行左外連線包含左邊表的全部行(不管右邊的表中是否存在與它們匹配的行),以及右邊表中全部匹配的行右外連線包含右邊表的全部行(不管左邊的表中是否存在與它們匹配的行),以及左邊表中全部匹配的行全外連線包含左、右兩個表的全部行,不管另外一邊的表中是否存在與它們匹配的行。
(H)(theta)
連線使用等值以外的條件來匹配左、右兩個表中的行交叉連線生成笛卡爾積-它不使用任何匹配或者選取條件,而是直接將一個數據源中的每個行與另一個數據源的每個行都一一匹配

在INFORMIX中連線表的查詢
如果FROM子句指定了多於一個表引用,則查詢會連線來自多個表的行。連線條件指定各列之間(每個表至少一列)進行連線的關係。因為正在比較連線條件中的列,所以它們必須具有一致的資料型別。


SELECT語句的FROM子句可以指定以下幾種型別的連線
FROM子句關鍵字        相應的結果集
CROSS JOIN        笛卡爾乘積(所有可能的行對)
INNER JOIN        僅對滿足連線條件的CROSS中的列
LEFT OUTER JOIN        一個表滿足條件的行,和另一個表的所有行
RIGHT OUTER JOIN        與LEFT相同,但兩個表的角色互換
FULL OUTER JOIN        LEFT OUTER 和 RIGHT OUTER中所有行的超集

2.2 內連線(Inner Join

內連線是最常見的一種連線,它頁被稱為普通連線,而E.FCodd最早稱之為自然連線。
下面是ANSI SQL-92標準
select *
from  t_institution i
inner join t_teller t
on i.inst_no = t.inst_no
where i.inst_no = "5801"
其中inner可以省略。
等價於早期的連線語法
select *
from t_institution i, t_teller t
where i.inst_no = t.inst_no
and i.inst_no = "5801"

2.3 外連線

2.3.1        左外連線(Left Outer Jion)


select *
from  t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
其中outer可以省略。

2.3.2        右外連線(Rigt Outer Jion)


select *
from  t_institution i
right outer join t_teller t
on i.inst_no = t.inst_no

2.3.3        全外連線(Full Outer)


全外連線返回參與連線的兩個資料集合中的全部資料,無論它們是否具有與之相匹配的行。在功能上,它等價於對這兩個資料集合分別進行左外連線和右外連線,然後再使用消去重複行的並操作將上述兩個結果集合併為一個結果集。
在現實生活中,參照完整性約束可以減少對於全外連線的使用,一般情況下左外連線就足夠了。在資料庫中沒有利用清晰、規範的約束來防範錯誤資料情況下,全外連線就變得非常有用了,你可以使用它來清理資料庫中的資料。
select *
from  t_institution i
full outer join t_teller t
on i.inst_no = t.inst_no

2.3.4        外連線與條件配合使用

當在內連線查詢中加入條件是,無論是將它加入到join子句,還是加入到where子句,其效果是完全一樣的,但對於外連線情況就不同了。當把條件加入到 join子句時,SQL Server、Informix會返回外連線表的全部行,然後使用指定的條件返回第二個表的行。如果將條件放到where子句中,SQL Server將會首先進行連線操作,然後使用where子句對連線後的行進行篩選。下面的兩個查詢展示了條件放置位子對執行結果的影響:
條件在join子句
select *
from  t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
and i.inst_no = “5801
結果是:
inst_no    inst_name            inst_no    teller_no  teller_name
5801       天河區               5801       0001       tom
5801       天河區               5801       0002       david
5802       越秀區
5803       白雲區
條件在where子句
select *
from  t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
where i.inst_no = “5801
結果是:
inst_no    inst_name            inst_no    teller_no  teller_name
5801       天河區               5801       0001       tom
5801       天河區               5801       0002       david

2.4 自身連線


自身連線是指同一個表自己與自己進行連線。這種一元連線通常用於從自反關係(也稱作遞迴關係)中抽取資料。例如人力資源資料庫中僱員與老闆的關係。
下面例子是在機構表中查詢本機構和上級機構的資訊。
select s.inst_no superior_inst, s.inst_name sup_inst_name, i.inst_no, i.inst_name
from t_institution i
join t_institution s
on i.superior_inst = s.inst_no

結果是:
superior_inst sup_inst_name        inst_no    inst_name
800           廣州市               5801       天河區
800           廣州市               5802       越秀區
800           廣州市               5803       白雲區


2.5 交叉(無限制) 連線


交叉連線用於對兩個源表進行純關係代數的乘運算。它不使用連線條件來限制結果集合,而是將分別來自兩個資料來源中的行以所有可能的方式進行組合。資料集合中一的每個行都要與資料集合二中的每一個行分別組成一個新的行。例如,如果第一個資料來源中有5個行,而第二個資料來源中有4個行,那麼在它們之間進行交叉連線就會產生20個行。人們將這種型別的結果集稱為笛卡爾乘積。
大多數交叉連線都是由於錯誤操作而造成的;但是它們卻非常適合向資料庫中填充例子資料,或者預先建立一些空行以便為程式執行期間所要填充的資料保留空間。
select *
from  t_institution i
cross join t_teller t
在交叉連線中沒有on條件子句

3 APPENDIX


3.1 A 參考資料與資源
        《Microsoft SQL Server r2000 Bile》Paul Nielsen
        Paul Nielsen的Web站點r
[url]www.isnotnull.com[/url]
3.2 註文章所有SQL在IBM Informix Dynamic Server Version 9.40.TC2E1測試通過


--

表A記錄如下:
aID        aNum
1           a20050111
2           a20050112
3           a20050113
4           a20050114
5           a20050115

表B記錄如下:
bID        bName
1            2006032401
2           2006032402
3           2006032403
4           2006032404
8           2006032408



實驗如下:
1.left join

sql語句如下:
select * from A
left join B
on A.aID = B.bID

結果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2
            a20050112         2              2006032402
3
            a20050113         3              2006032403
4
            a20050114         4              2006032404
5
            a20050115         NULL       NULL
(所影響的行數為 5 行)

結果說明:
        left join是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為準的.
換句話說,左表(A)的記錄將會全部表示出來,而右表(B)只會顯示符合搜尋條件的記錄(例子中為: A.aID = B.bID).
B表記錄不足的地方均為NULL.

2.right join

sql語句如下:
select * from A
right join B
on A.aID = B.bID

結果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2
            a20050112         2              2006032402
3
            a20050113         3              2006032403
4
            a20050114         4              2006032404
NULL    NULL                   8              2006032408
(所影響的行數為 5 行)

結果說明:
        仔細觀察一下,就會發現,和left join的結果剛好相反,這次是以右表(B)為基礎的,A表不足的地方用NULL填充.

3.inner join

sql語句如下:
select * from A
innerjoin B
on A.aID = B.bID

結果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2
            a20050112         2              2006032402
3
            a20050113         3              2006032403
4
            a20050114         4              2006032404

結果說明:
        很明顯,這裡只顯示出了 A.aID = B.bID的記錄.這說明inner join並不以誰為基礎,它只顯示符合條件的記錄.


-----------------[以下為網上的一點資料]------------------
LEFT JOIN操作用於在任何的 FROM 子句中,組合來源表的記錄。使用 LEFT JOIN 運算來建立一個左邊外部聯接。左邊外部聯接將包含了從第一個(左邊)開始的兩個表中的全部記錄,即使在第二個(右邊)表中並沒有相符值的記錄。

語法:FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2

說明:table1, table2引數用於指定要將記錄組合的表的名稱。
field1, field2引數指定被聯接的欄位的名稱。且這些欄位必須有相同的資料型別及包含相同型別的資料,但它們不需要有相同的名稱。
compopr引數指定關係比較運算子:"=", "<", ">", "<=", ">=" 或 "<>"。
如果在INNER JOIN操作中要聯接包含Memo 資料型別或 OLE Object 資料型別資料的欄位,將會發生錯誤。