SQL多表查詢(SQL 92 與SQL 99詳解)

連接查詢

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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章