原鏈接地址: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
SELECT a.[UserID],b.[Name],sum (c.[Money]+c.[Bank])as TotalMoneyFROM Table1 a(nolock)
LEFTJOIN Table2 b(nolock) on a.[UserID]= b.[UserID]
LEFTJOIN Table3 c(nolock) ON b.[UserID]=c.[UserID]
WHERE a.[UserID]= b.[UserID]and a.[UserID]= c.[UserID]and a.[Time]>='2005-01-01'AND a.[Time]<='2006-12-31'
GROUPBY a.[UserID],b.[Name]
ORDERBY a.[Time]DESC
優化一下
================================================================================
Left Join 語法:
FROM Table1 a(nolock)
LEFTJOIN Table3 c(nolock) ON a.[UserID]=c.[UserID], Table2 b(nolock)
WHERE a.[UserID]= b.[UserID]and a.[Time]>='2005-01-01'AND a.[Time]<='2006-12-31'
GROUPBY a.[UserID],b.[Name]
ORDERBY a.[Time]DESC
table1 leftjoin table2 on 條件1
leftjoin table3 on 條件2
leftjoin table4 on 條件3
where 條件4
GROUP BY 說明:
在select 語句中可以使用group by 子句將行劃分成較小的組,然後,使用聚組函數返回每一個組的彙總信息,另外,可以使用having子句限制返回的結果集。group by 子句可以將查詢結果分組,並返回行的彙總信息Oracle 按照group by 子句中指定的表達式的值分組查詢結果。
在帶有group by 子句的查詢語句中,在select 列表中指定的列要麼是group by 子句中指定的列,要麼包含聚組函數
select max(sal),job emp group by job;
(注意max(sal),job的job並非一定要出現,但有意義)
查詢語句的select 和group by ,having 子句是聚組函數唯一出現的地方,在where 子句中不能使用聚組函數。
select deptno,sum(sal) from emp where sal>1200 group by deptno having sum(sal)>8500 order by deptno;
當在gropu by 子句中使用having 子句時,查詢結果中只返回滿足having條件的組。在一個sql語句中可以有where子句和having子句。having 與where 子句類似,均用於設置限定條件
where 子句的作用是在對查詢結果進行分組前,將不符合where條件的行去掉,即在分組之前過濾數據,條件中不能包含聚組函數,使用where條件顯示特定的行。
having 子句的作用是篩選滿足條件的組,即在分組之後過濾數據,條件中經常包含聚組函數,使用having 條件顯示特定的組,也可以使用多個分組標準進行分組。
查詢每個部門的每種職位的僱員數
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; |
以下爲測試例子
--列出部門ID爲3的部門和員工信息,不管該部門是否有員工
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;