Id_P
|
LastName
|
FirstName
|
Address
|
City
|
---|---|---|---|---|
1
|
Adams
|
John
|
Oxford Street
|
London
|
2
|
Bush
|
George
|
Fifth Avenue
|
New York
|
3
|
Carter
|
Thomas
|
Changan Street
|
Beijing
|
Id_O
|
OrderNo
|
Id_P
|
---|---|---|
1
|
77895
|
3
|
2
|
44678
|
3
|
3
|
22456
|
1
|
4
|
24562
|
1
|
5
|
34764
|
65
|
LastName
|
FirstName
|
OrderNo
|
---|---|---|
Adams
|
John
|
22456
|
Adams
|
John
|
24562
|
Carter
|
Thomas
|
77895
|
Carter
|
Thomas
|
44678
|
Bush
|
George
|
這兩天,在研究SQL語法中的inner join多表查詢語法的用法,經過學習,發現一個SQL命令,居然涉及到不少線性代數方面的知識,現將這些知識系統地記錄以下:數據庫
使用關係代數合併數據
1 關係代數
合併數據集合的理論基礎是關係代數,它是由E.F.Codd於1970年提出的。
在關係代數的形式化語言中:
? 用表、或者數據集合表示關係或者實體。
? 用行表示元組。
? 用列表示屬性。
關係代數包含如下8個關係運算符
? 選取――返回知足指定條件的行。
? 投影――從數據集合中返回指定的列。
? 笛卡爾積――是關係的乘法,它將分別來自兩個數據集合中的行以全部可能的方式進行組合。
? 並――關係的加法和減法,它能夠在行的方向上合併兩個表中的數據,就像把一個表壘在另外一個表之上同樣。
? 交――返回兩個數據集合所共有的行。
? 差――返回只屬於一個數據集合的行。
? 鏈接――在水平方向上合併兩個表,其方法是:將兩個表中在共同數據項上相互匹配的那些行合併起來。
? 除――返回兩個數據集之間的精確匹配。
此外,做爲一種實現現代關係代數運算的方法,SQL還提供了:
? 子查詢――相似於鏈接,但更靈活;在外部查詢中,方式可使用表達式、列表或者數據集合的地方均可以使用子查詢的結果。
本章將主要講述多種類型的鏈接、簡單的和相關的子查詢、幾種類型的並、關係除以及其餘的內容。
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條件子句
經過以上知識,還真是系統地學習了一番,發現inner join其實能夠經過最初的多表查詢方式來實現,例如:學習
select * from t_institution i ,t_teller t where i.inst_no = t.inst_no and i.inst_no = "5801"spa
其實,inner join就是對多表查詢的一種解決方案而已。而外鏈接,仍是有其特定的用處的,實際上就至關於一個開區間,而內鏈接就是一個閉區間。orm