oracle外連接,Oracle中Left Outer Join和外關聯(+)的區別

原鏈接地址:http://blog.csdn.net/jackpk/article/details/5969187

Oracle的left join中on和where的區別 2009-09-28 15:20

URL: http://hi.baidu.com/bfsll/blog/item/3a884e2f0fc905321e3089a7.html

今天遇到一個求某月所有天數的統計結果,如果某日的結果是0也需要顯示出來,即:

日期                  交易次數   交易金額

2009-4-01           1              10

2009-4-02           2              20

2009-4-03           0              0

2009-4-04           5              50

....


一開始我用的左連接,用on做爲兩表關聯條件,用where作爲過濾條件,但是發現0的數據根本不顯示,後來把where關鍵字去掉,把過濾條件都放到on裏,問題解決,網上一搜,找到了答案:

數據庫在通過連接兩張或多張表來返回記錄時,都會生成一張中間的臨時表,然後再將這張臨時表返回給用戶

     在使用left jion時,on和where條件的區別如下:

1、 on條件是在生成臨時表時使用的條件,它不管on中的條件是否爲真,都會返回左邊表中的記錄

2、where條件是在臨時表生成好後,再對臨時表進行過濾的條件。這時已經沒有left join的含義(必須返回左邊表的記錄)了,條件不爲真的就全部過濾掉

      假設有兩張表:

表1 tab1:

id size

1 10

2 20

3 30

表2 tab2:

size name

10    AAA

20    BBB

20    CCC


兩條SQL:
1、select * form tab1 left join tab2 on (tab1.size = tab2.size) where tab2.name=’AAA’
2、select * form tab1 left join tab2 on (tab1.size = tab2.size and tab2.name=’AAA’)

第一條SQL的過程:

1、中間表
on條件:
tab1.size = tab2.size

tab1.id    tab1.size    tab2.size     tab2.name

1               10                   10               AAA

2               20                   20               BBB

2               20                   20               CCC

3               30                   (null)           (null)

2、再對中間表過濾
where 條件:
tab2.name=’AAA’

tab1.id       tab1.size        tab2.size     tab2.name

1                  10                  10              AAA


第二條SQL的過程:

1、中間表
on條件:
tab1.size = tab2.size and tab2.name=’AAA’
(條件不爲真也會返回左表中的記錄)

tab1.id      tab1.size         tab2.size       tab2.name

1               10                     10                   AAA

2               20                    (null)                (null)

3               30                    (null)                (null)

    其實以上結果的關鍵原因就是left join,right join,full join的特殊性,不管on上的條件是否爲真都會返回left或right表中的記錄,full則具有left和right的特性的並集。 而inner jion沒這個特殊性,則條件放在on中和where中,返回的結果集是相同的。

轉自:http://hi.baidu.com/%BA%D3%B1%B1%B6%FE%C9%D9/blog



多表鏈接 Left join

URL: http://www.cnblogs.com/windamy/articles/585555.html


一個我寫的實例:其中多表連接,一共連接了3個表。使用聚集函數SUM,用到了GROUP BY

None.gifSELECT a.[UserID],b.[Name],sum (c.[Money]+c.[Bank])as TotalMoney
None.gif
FROM Table1 a(nolock)
None.gif
LEFTJOIN Table2 b(nolock) on a.[UserID]= b.[UserID]
None.gif
LEFTJOIN Table3 c(nolock) ON b.[UserID]=c.[UserID]
None.gif
None.gif
WHERE  a.[UserID]= b.[UserID]and a.[UserID]= c.[UserID]and a.[Time]>='2005-01-01'AND a.[Time]<='2006-12-31'
None.gif
None.gif
GROUPBY a.[UserID],b.[Name]
None.gif
None.gif
ORDERBY a.[Time]DESC


優化一下

================================================================================
Left Join 語法:

None.gifSELECT a.[UserID],b.[Name],sum (c.[Money]+c.[Bank])as TotalMoney
None.gif
FROM Table1 a(nolock)
None.gif
LEFTJOIN Table3 c(nolock) ON a.[UserID]=c.[UserID],  Table2 b(nolock)
None.gif
None.gif
WHERE  a.[UserID]= b.[UserID]and a.[Time]>='2005-01-01'AND a.[Time]<='2006-12-31'
None.gif
None.gif
GROUPBY a.[UserID],b.[Name]
None.gif
None.gif
ORDERBY a.[Time]DESC


None.gifselect*from
None.giftable1  
leftjoin   table2   on   條件1  
None.gif
leftjoin   table3   on
  條件2  
None.gif
leftjoin   table4   on
  條件3  
None.gif
where   條件4


GROUP BY 說明:

None.gifgroup by
None.gif
None.gif    在select 語句中可以使用group by 子句將行劃分成較小的組,然後,使用聚組函數返回每一個組的彙總信息,另外,可以使用having子句限制返回的結果集。group by 子句可以將查詢結果分組,並返回行的彙總信息Oracle 按照group by 子句中指定的表達式的值分組查詢結果。
None.gif
None.gif   在帶有group by 子句的查詢語句中,在select 列表中指定的列要麼是group by 子句中指定的列,要麼包含聚組函數
None.gif
None.gif   select max(sal),job emp group by job;
None.gif   (注意max(sal),job的job並非一定要出現,但有意義)
None.gif
None.gif   查詢語句的select 和group by ,having 子句是聚組函數唯一出現的地方,在where 子句中不能使用聚組函數。
None.gif
None.gif  select deptno,sum(sal) from emp where sal>1200 group by deptno having sum(sal)>8500 order by deptno;
None.gif
None.gif  當在gropu by 子句中使用having 子句時,查詢結果中只返回滿足having條件的組。在一個sql語句中可以有where子句和having子句。having 與where 子句類似,均用於設置限定條件
None.gif
None.gif  where 子句的作用是在對查詢結果進行分組前,將不符合where條件的行去掉,即在分組之前過濾數據,條件中不能包含聚組函數,使用where條件顯示特定的行。
None.gif  having 子句的作用是篩選滿足條件的組,即在分組之後過濾數據,條件中經常包含聚組函數,使用having 條件顯示特定的組,也可以使用多個分組標準進行分組。
None.gif
None.gif  查詢每個部門的每種職位的僱員數
None.gif  select deptno,job,count(*) from emp group by deptno,job;



Oracle表連接方式(2008-08-06 16:29:54)

http://blog.sina.com.cn/s/blog_4cfcdbf00100a5ri.html




Oracle 的左連接和右連接

url: http://blog.csdn.net/yaba213/archive/2009/06/15/4270493.aspx


PL-SQL中,左連接和右連接以如下方式來實現
查看如下語句:
SELECT emp_name, dept_name FORM Employee, Department   WHERE Employee.emp_deptid(+) = Department.deptid
此SQL文使用了右連接,即“(+)”所在位置的另一側爲連接的方向,右連接說明等號右側的所有記錄均會被顯示,
無論其在左側是否得到匹配,也就是說上例中無論會不會出現某個部門沒有一個員工的情況,這個部門的名字都會在查詢結果中出現。

反之:
SELECT emp_name, dept_name FORM Employee, Department WHERE Employee.emp_deptid = Department.deptid(+)
則是左連接,無論這個員工有沒有一個能在Department表中得到匹配的部門號,這個員工的記錄都會被顯示

一般的相等連接:
select * from a, b where a.id = b.id;
這個就屬於內連接。

對於外連接 :
Oracle 中可以使用“(+) ”來表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN  

LEFT OUTER JOIN:左外關聯  
SELECT e.last_name, e.department_id, d.department_name  
FROM employees e  
LEFT OUTER JOIN departments d  
ON (e.department_id = d.department_id);  
等價於  
SELECT e.last_name, e.department_id, d.department_name  
FROM employees e, departments d  
WHERE e.department_id=d.department_id(+)  
結果爲:所有員工及對應部門的記錄,包括沒有對應部門編號department_id的員工記錄。  

RIGHT OUTER JOIN:右外關聯  
SELECT e.last_name, e.department_id, d.department_name  
FROM employees e  
RIGHT OUTER JOIN departments d  
ON (e.department_id = d.department_id);  
等價於  
SELECT e.last_name, e.department_id, d.department_name  
FROM employees e, departments d  
WHERE e.department_id(+)=d.department_id  
結果爲:所有員工及對應部門的記錄,包括沒有任何員工的部門記錄。  

FULL OUTER JOIN:全外關聯  
SELECT e.last_name, e.department_id, d.department_name  
FROM employees e  
FULL OUTER JOIN departments d  
ON (e.department_id = d.department_id);  
結果爲:所有員工及對應部門的記錄,包括沒有對應部門編號department_id的員工記錄和沒有任何員工的部門記錄。


外關聯是Oracle數據庫的專有語句

Left Outer Join則是SQL-92的標準語句

通常認爲這兩個SQL是可以等效的,但還是有些細微的差別。

一般說來,外關聯的等值條件等效於Left Outer Join中的on語句;兩個where中其他語句是一樣的。

但是Left Outer Join中的其他條件(非表連接)出現在On關鍵詞後面還是出現在Where關鍵詞後面是不一樣的,這樣的語句很難用外關聯進行同義轉義

下面我們先看一個測試數據,和一個測試案例

創建一個部門表和員工表


CREATE TABLE departments

(

depIDNUMBER(38,0),

depName VARCHAR2(20),

delFlag NUMBER(1,0)

);

CREATE TABLE employees

(

empIDNUMBER(38,0),

empName VARCHAR2(20),

depIDNUMBER(38,0),

delFlag NUMBER(1,0)

);

INSERT INTO departments VALUES(1,'Finacle',0);

INSERT INTO departments VALUES(2,'Marketing',0);

INSERT INTO departments VALUES(3,'HR',1);

INSERT INTO departments VALUES(4,'IT',0);

INSERT INTO employees VALUES(1,'wbq',1,0);

INSERT INTO employees VALUES(2,'czh',2,0);

INSERT INTO employees VALUES(3,'chh',1,0);

INSERT INTO employees VALUES(4,'wal',2,0);

INSERT INTO employees VALUES(5,'ddd',3,0);

COMMIT;

以下爲測試例子


--列出部門ID3的部門和員工信息,不管該部門是否有員工

SELECT d.depID,d.depName,e.empName

FROM departments d

LEFT OUTER JOIN employees e

ON d.depID = e.depID

WHERE d.depID =3

ORDER BY d.depID;

--和上面等效

SELECT d.depID,d.depName,e.empName

FROM departments d, employees e

WHERE d.depID = e.depID(+)

AND d.depID =3

ORDER BY d.depID;

--該例子可能不是很恰當,d.depID=3表示首先進行全左連接,然後查找depID=3的紀錄,如果該部門中找不到對應的員工,則該部門員工則爲NULL,同時都顯示部門信息。

SELECT d.depID,d.depName,e.empName d.delflag

FROM departments d

LEFT OUTER JOIN employees e

ON d.depID = e.depID AND e.depID=3

ORDER BY d.depID;

--和上面不等價,差別在於能夠找到無對應員工的部門和有對應員工的部門,卻找不到該部門無員工的部門。

SELECT d.depID,d.depName,e.empName,d.delflag

FROM departments d, employees e

WHERE d.depID = e.depID(+)

AND (e.depID=3 or e.depID is NULL)

ORDER BY d.depID;


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