1. 程式人生 > >sql多表關聯查詢使用JOIN..ON與where的優化場景

sql多表關聯查詢使用JOIN..ON與where的優化場景

先說明原因:

關鍵字: on

資料庫在通過連線兩張或多張表來返回記錄時,都會生成一張中間的臨時表,然後再將這張臨時表返回給使用者。

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

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

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

假設有兩張表:

表1:tab2

idsize
110
220
330

表2:tab2

sizename
10AAA
20BBB
20CCC

兩條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.idtab1.sizetab2.sizetab2.name
11010AAA
22020BBB
22020CCC
330(null)(null)
2、再對中間表過濾
where 條件:
tab2.name=’AAA’
tab1.idtab1.sizetab2.sizetab2.name
11010AAA
第二條SQL的過程:
1、中間表
on條件:
tab1.size = tab2.size and tab2.name=’AAA’
(條件不為真也會返回左表中的記錄)
tab1.idtab1.sizetab2.sizetab2.name
11010AAA
220(null)(null)
330(null)(null)

實戰練習

1.首先先建立兩個表

create table table1
(
  mon varchar2(14),
dep number(4),
yj number(4)
)
insert into table1 values ('一月份',1,10);
insert into table1 values ('一月份',2,10);
insert into table1 values ('一月份',3,5);
insert into table1 values ('二月份',2,8);
insert into table1 values ('二月份'
,4,9); insert into table1 values ('二月份',3,8); create table table2 ( dep number(4), dname varchar2(30) ) insert into table2 values(1,'國內業務一部'); insert into table2 values(2,'國內業務二部'); insert into table2 values(3,'國內業務三部'); insert into table2 values(4,'國際業務部');

2.要求查出每個部門一月份,二月份的業績

查出結果如下


3 用以下where語句增加最後的過濾條件在特定場景下肯定是可以的 (但是鑑於這裡是要1~4月全部展示,所以where子句還是不符合條件,在這裡列出是為了說明where是在on條件執行之後增加過濾條件)

select t0.dep as dep,t0.dname as 部門名稱 , t1.yj as 一月份業績 , t2.yj as 二月份業績
from table2 t0
  left join  table1 t1 on  t0.dep=t1.dep
  left join table1 t2 on  t0.dep=t2.dep
where t1.mon='一月份' and t2.mon='二月份'
order by t0.dep

4. 接下來把where條件去掉看查出來的資料有10條,可以發現這其中沒有 t1.mon='一月份' and t2.mon='二月份'的限定條件,

    table2表的國際業務一部 (dep=1)與 table1表的一月份(dep=1)的業績為10(yj=10) 匹配2次,分別匹配出一條一月份的業績和二月份的業績 ,因為國際業務一部二月份麼有業績,所以這明顯是錯誤的匹配 (增加了額外的中間表數量)

5. 如果能在匹配之前先對應加上t1.mon='一月份' 或者  t2.mon='二月份'的限定條件,如果沒有滿足限定條件,後面的t0.dep=t1.dep就不會執行,這樣就會至少在中間表中會少一條資料, 假如再使用where過濾就會減少過濾運算元量

select t0.dep as dep,t0.dname as 部門名稱 , t1.yj as 一月份業績 , t2.yj as 二月份業績
from table2 t0
  left join  table1 t1 on t1.mon='一月份' and t0.dep=t1.dep
  left join table1 t2 on t2.mon='二月份' and t0.dep=t2.dep
order by t0.dep

  

參考文章:https://www.cnblogs.com/wlzhang/p/4532587.html

https://www.cnblogs.com/lykbk/p/aefweere45454545454.html