連接查詢
Join表操作符對兩個輸入表進行了操作。連接有三種基本類型:交叉連接,內連接,外鏈接。這三種連接的區別是它們採用的邏輯查詢處理步驟各部相同,每種連接都有一套不同的步驟。交叉連接只有一個步驟—笛卡爾積;內連接有兩個步驟—笛卡爾積,過濾;外鏈接有三個步驟—笛卡爾積,過濾,添加外部行。
SQL語句的歷史版本
SQL89(比較多)
SQL92(標準,又稱sql2)
SQL99(標準,又稱sql3)
就目前爲止 , SQL多表查詢可總結爲兩種標準 , 即 : SQL92標準和SQL99標準 ; 92標準相對與99標準來說 , 語句上比較冗雜 , 外連接不太容易識別 。但也有它的便捷之處。總之無論如何,接下來就是對這兩種標準多表查詢的詳解
多表關聯查詢包括
笛卡爾積
等值關聯查詢
非等值關聯查詢
左外連接
右外連接
全外連接
自連接
–SQL92 語法
笛卡爾積(將兩張表的數據拼接在一起,總記錄數爲兩張表記錄量的乘積 ( 表*表 ) )
select * from emp e,dept d
等值連接 ( 在where後的條件爲等值條件 , 即: “=” )
select * from emp t, dept d where t.deptno = d.deptno;
非等值連接 ( 在where後的條件爲非等值條件 , 例如:> , < , >= , <= 等 )
select e.ename,s.grade from emp e, salgrade s where e.sal between s.losal and s.hisal;
自連接 ( 在where後的條件 , 用自身字段之間的關連作爲條件 )
select e1.ename,e2.ename from emp e1,emp e2 where e1.mgr = e2.empno;
外連接 (在滿足一張表的內容都顯示的基礎上,連接另外一張表,如果連接匹配則正常顯示,連接不匹配,另外一張表補null)
select e.ename,d.dname from emp e, dept d where e.deptno = d.deptno(+) ;
–SQL 99 語法 :
語法形式 : select a.column,b.column from 表a 連接類型 JOIN 表b on 連接條件
交叉連接 (CROSS JOIN) : 可理解爲92語法中的笛卡爾積
select * from emp cross join dept;
自然連接 (NATURAL JOIN):根據兩張表中相同字段名稱,進行等值連接
select * from emp natural join dept;
內連接 (INNER JOIN)(INNER關鍵字可以省略)
–(1)等值連接
select e.ename, d.dname
from emp e
INNER JOIN dept d
on e.deptno = d.deptno
where e.sal > 2000
–(2)非等值連接
select e.ename, s.grade
from emp e
INNER JOIN salgrade s
on e.sal between s.losal and s.hisal
–(3)自連接
select e1.ename || '的上司是' || e2.ename
from emp e1
INNER JOIN emp e2
on e1.mgr = e2.empno
外連接 (OUTER關鍵字可以省略)
–(1)LEFR OUTER JOIN(左外連接)
select * from emp e LEFT OUTER JOIN dept d on e.deptno = d.deptno
–(2)RIGHT OUTER JOIN(右外連接)
select * from emp e RIGHT OUTER JOIN dept d on e.deptno = d.deptno
–(3)FULL OUTER JOIN(全外連接)
select * from emp e FULL OUTER JOIN dept d on e.deptno = d.deptno
接下來詳細講解各種連接
交叉連接
交叉聯接是一種最簡單的聯接,交叉聯接只實現一個笛卡爾積即可。這一步就是對兩張表進行操作,把它們聯接起來,生成兩者的笛卡爾積。也就是將一個輸入表的每行和另一張表的每行進行匹配。如果一張表有n行,另一張表有m行,將得到m * n行。
ANSI SQL-99:Cross Join
ANSI SQL-92:在兩張表間放置一個逗號
內連接(ANSI SQL-99標準提出來的概念)
–內連接(整合了ANSI SQL-92的等值連接,不等值連接,自連接)
(1)
--等值連接
--不等值連接
(2)
--非自連接
--自連接
內連接要應用兩個邏輯查詢處理步驟:它首先像交叉聯接一樣,對兩個輸入表進行笛卡爾積運算:然後根據用戶指定的謂詞對結果進行過濾。和交叉聯接一樣,內聯接也有兩種標準語法。
ANSI SQL-99:Inner Join 或者 Join(由於內連接是默認的聯接方式,所以也可以只寫Join)
ANSI SQL-92:在兩張表間放置一個逗號,在查詢的where子句中寫過濾條件。
強烈推薦使用Inner Join,因爲假如你忘記寫過濾條件(on),執行時SQL會報錯。而如果使用SQL-92語法,則不會報錯。那麼這個內連接就變成交叉連接了! 而且實際開發中SQL語句會非常的複雜,寫錯的概率就很大了。
補充一下:
1.組合連接
有時候過濾條件不止一個,這時候就要用and來連接多個條件,這就叫做組合連接。例如:Table2表中定義了一個外鍵(col1和col2),引用了Table1表的col1和col2列,現在要寫一個根據主外鍵關係來連接兩個表的查詢語句。該條件如下:
from table1 as t1
join table2 as t2
on t1.col1 = t2.col1 and t1.col2 = t2.col2
2.多表連接
一個聯接表運算符只對兩個表進行操作,而一條查詢語句可以包含多個聯接。通常,當FROM子句中包含多個表運算符時,表運算符在邏輯上是按從左到右的順序處理的。也就是說,第一個表運算符的結果將作爲第二個表運算符的輸入,第二個表運算符的結果將作爲第三個運算符左邊的輸入,以此類推。
外連接
外連接會應用內連接所應用的兩個邏輯處理步驟(笛卡爾積和On過濾),此外還多一個外連接特有的第三步:添加外部行。
ANSI SQL-92:在原有等值連接的基礎上加上左邊或者右邊加上(+),實現外連接查詢
ANSI SQL-99:
INNER JOIN(也可簡寫爲JOIN): 如果表中有至少一個匹配,則返回行
LEFT JOIN: 即使右表中沒有匹配,也從左表返回所有的行
RIGHT JOIN: 即使左表中沒有匹配,也從右表返回所有的行
FULL JOIN: 只要其中一個表中存在匹配,就返回行
解釋:在外連接中,要把一個表標記爲“保留的”表,可以在表名之間使用關鍵字LEFT OUT JOIN、RIGHT OUTER JOIN ,以及 FULL OUTER JOIN,其中 OUTER 失鍵字是可選的。 LEFT關鍵字表示左邊表的行是保留的關鍵字表示右邊表的行是保留的,而FULL 關鍵字則表示左右兩邊表的行都是保留的。外聯接的第三個邏輯杏詢處理步驟就是要識別保留表中按照ON條件在另一個表找不到與之匹配的那些行,再把這些行添加到聯接 的前兩個步驟生成的結果表中:對於來自聯接的非保留表的那些列,追加的外部行中的這些列則用NULL作爲佔位符。
補充一下:自然連接:
自然連接是在兩張表中尋找那些數據類型和列名都相同的字段,然後自動地將他們連接起來,並返回所有符合條件按的結果。
自然連接無需指定連接列,sql會檢查兩個表中是否相同名稱的列,且假設他們在連接條件中使用,並且在連接條件中僅包含一個連接列。不允許使用on語句,不允許指定顯示列,顯示列只能用*表示(oracle環境下測 試的)。對於每種連接類型(除了交叉連接外),均可指定natural。
最後用下面例子來總結一下知識點:
---多表聯合查詢
---當需要獲取的數據分佈在多張表中使用多表聯合查詢
---SQL92方式
---笛卡爾積:將多個表的數據進行一一對應,所得到結果爲多表的笛卡爾積.
---結果數量爲所有表數量的乘積
seelct * from emp,dept;
---等值鏈接
----先做表的笛卡爾積,然後篩選,篩選條件爲等值篩選.
---查詢員工的姓名,工作,薪資,部門名稱
select * from emp,dept where dept.deptno=emp.deptno;---等值連接查詢
---可以直接在select子句中使用字段直接獲取數據,但是效率低,建議字段前加上表名
---注意:如果是公共字段必須聲明表名
select * from emp e,dept d where d.deptno=e.deptno;
---不等值鏈接
----查詢員工的姓名,工作,工資,工資等級
select * from emp e,salgrade s where e.sal>=s.losal and e.sal<= s.hisal;
---自連接
----相當於自己和自己做笛卡爾積
----查詢員工姓名,工作,薪資,以及上級領導姓名
select e1.ename,e1.job,e1.sal,e2.ename from emp e1,emp e2 where e1.mgr=e2.empno;
---外鏈接
----左外鏈接
---查詢員工姓名,工作,薪資,部門名稱以及沒有部門的員工信息
select * from emp e,dept d where e.deptno=d.deptno(+);
----右外鏈接
---查詢員工姓名,工作,薪資,部門名稱以及沒有員工的部門
select * from emp e,dept d where e.deptno(+)=d.deptno;
----SQL99多表查詢
----注意1:依然可以給表添加別名
----注意2;如果使用on或則usering關鍵字必須對結果進行篩選,必須使用inner join關鍵字組員於表與表的連接,其中inner可以省去
----注意3:外連接的outer關鍵字可以不寫
----注意4:依然可以使用排序等關鍵字
----1.笛卡爾積:使用cross join關鍵字
-----select 內容 from 表名 cross join
-----查詢員工及其部門
select * from emp cross join dept;
----2.篩選
-----自然連接:使用關鍵字natrual join
----使用:select 內容 from 表名 natural join 表名
select* from emp natural join dept;
---特點1:底層是笛卡爾積,按照同名同值字段自動進行等值篩選
---缺點1:如果想按照字段名不同,但是字段值不同篩選怎麼辦?
----缺點2:如果只想按照部分字段結果篩選怎麼辦?
----解決1:使用using關鍵字
--作用1:指明使用指定的字段對聯合查詢的結果進行等值篩選
--注意:指明的字段必須是兩邊同名同值字段
--使用:select 內容 from 表名 inner join 表名 using(字段名)
select * from emp inner join dept using(deptno,ename);--底層相當於先做了一個笛卡爾積,再進行等值篩選
------解決2:使用on關鍵字,進行自定義鏈接查詢
----注意:普通篩選使用where篩選不使用on 好處:便於閱讀
----使用:select 內容 from 表名 inner join 表名 on 連接條件 where 普通篩選條件
select * from emp inner join dept on emp.deptno=dept.deptno where job='SALESMAN';
------內連接
---1.等值鏈接
----先做表的笛卡爾積,然後篩選,篩選條件爲等值篩選.
---查詢員工的姓名,工作,薪資,部門名稱
select * from emp inner join dept on dept.deptno=emp.deptno;---等值連接查詢
---可以直接在select子句中使用字段直接獲取數據,但是效率低,建議字段前加上表名
---注意:如果是公共字段必須聲明表名
select * from emp e inner join dept d on d.deptno=e.deptno;
---2.不等值鏈接
----查詢員工的姓名,工作,工資,工資等級
select * from emp e,salgrade s where e.sal>=s.losal and e.sal<= s.hisal;
---3.自連接
-----查詢員工姓名,工作,薪資,以及上級領導姓名
select e1.*,e2.ename from emp e1 inner join emp e2 on e1.mgr=e2.empno;
------外連接
----左外連接:select 內容 from 表名 left outer join 表名 on 篩選條件
---查詢員工姓名,工作,薪資,部門名稱以及沒有部門的員工信息
select * from emp e left outer join dept d on d.deptno=e.deptno;
----右外連接:select 內容 from 表名 right outer join 表名 on 篩選條件
---查詢員工姓名,工作,薪資,部門名稱以及沒有員工的部門
select * from emp e right outer join dept d on d.deptno=e.deptno;
----全外連接:select 內容 from 表名 fill outer join 表名 on 篩選條件
select * from emp e full outer join dept d on d.deptno=e.deptno;