1. 程式人生 > >SQL中各種Join語句(left、right、full、inner)的區別

SQL中各種Join語句(left、right、full、inner)的區別

iamlaosong文

實際工作中常常需要將多個表的查詢結果合成的一個查詢中,我一般採用join語句進行連線,用的最多的就是left join,這麼多join的差別是什麼呢?簡單的說就是最終結果以誰為主的問題。下面是個查詢語句例項:

select aa.city, aa.ssxs, aa.zj_code, aa.zj_mc, bb.clct, cc.dlv
  from sncn_zd_jg aa
  left join (select t.clct_bureau_org_code zj_code, count(*) clct
               from tb_evt_mail_clct t
              where t.clct_date = trunc(sysdate - 1)
              group by t.clct_bureau_org_code) bb on bb.zj_code =
                                                     aa.zj_code
  left join (select t.dlv_bureau_org_code zj_code, count(*) dlv
               from tb_evt_dlv t
              where t.dlv_date = trunc(sysdate - 1)
              group by t.dlv_bureau_org_code) cc on cc.zj_code = aa.zj_code
 order by aa.city, aa.ssxs, aa.zj_code, aa.zj_mc

1、left join

左連線自然以連線條件的左邊為主,即前面一個查詢記錄(左邊)為主,如果前面的記錄中無內容,後面的查詢結果即使有內容也會被丟棄,如果前面的記錄中有內容,後面的查詢結果無內容,也會保留這一條記錄,只是後面的查詢結果為空而已,如下圖所示:


2、right join

理解了左連線,右連線理解也就簡單了,即以後面的結果為主,前面的結果如果沒有,則為空。

3、full join

全連線則是保留所有的查詢記錄,沒有的對應位置則為空。

4、inner join

和全連線相反,只保留所有查詢都有結果的記錄,其它都丟棄。

內連線另一種寫法是把查詢結果或者表都放在from關鍵字後面,而在條件語句中加上連線條件,這種寫法更常見,特別是多表關聯查詢的時候。

如:

select * from t1,t2 where t1.id=t2.id;

上面內連線的查詢語句也可以改成如下形式:

select aa.city, aa.ssxs, aa.zj_code, aa.zj_mc, bb.clct, cc.dlv
  from sncn_zd_jg aa,
       (select t.clct_bureau_org_code zj_code, count(*) clct
          from tb_evt_mail_clct t
         where t.clct_date = trunc(sysdate - 1)
         group by t.clct_bureau_org_code) bb,
       (select t.dlv_bureau_org_code zj_code, count(*) dlv
          from tb_evt_dlv t
         where t.dlv_date = trunc(sysdate - 1)
         group by t.dlv_bureau_org_code) cc
 where aa.zj_code = bb.zj_code
   and aa.zj_code = cc.zj_code
 order by aa.city, aa.ssxs, aa.zj_code, aa.zj_mc

同理,左連線也可改寫,只是需要在條件處後表字段後面加上“(+)”,如下所示:
select aa.city, aa.ssxs, aa.zj_code, aa.zj_mc, bb.clct, cc.dlv
  from sncn_zd_jg aa,
       (select t.clct_bureau_org_code zj_code, count(*) clct
          from tb_evt_mail_clct t
         where t.clct_date = trunc(sysdate - 1)
         group by t.clct_bureau_org_code) bb,
       (select t.dlv_bureau_org_code zj_code, count(*) dlv
          from tb_evt_dlv t
         where t.dlv_date = trunc(sysdate - 1)
         group by t.dlv_bureau_org_code) cc
 where aa.zj_code = bb.zj_code(+)
   and aa.zj_code = cc.zj_code(+)
 order by aa.city, aa.ssxs, aa.zj_code, aa.zj_mc

左連線的這種寫法似乎也是oracle獨有的(非標用法),其它資料庫系統並不支援。至於右連線嘛,也可以將“(+)”寫在左邊,或者將表或查詢結果調換位置,變成左連線。不過全連線似乎不能用這種形式。

實際工作中用的最多的是左連線,為了儘可能全面,第一個查詢應該選擇一個最全面的查詢,如下面這個例子:

select aa.cljds, aa.lybcf, bb.jkbcf, cc.ckbcf, dd.zybcf, ee.hkbcf
  from (select t.pyjds cljds, sum(t.feiyong) lybcf
          from emsapp_js_ly_bcf t
         where t.jsrq between to_date('2017-1-1', 'yyyy-mm-dd') and
               to_date('2017-1-1', 'yyyy-mm-dd')
         group by t.pyjds) aa
  left join (select t.cljds, sum(t.feiyong) jkbcf
               from emsapp_js_jk_bcf t
              where t.jsrq between to_date('2017-1-1', 'yyyy-mm-dd') and
                    to_date('2017-1-1', 'yyyy-mm-dd')
              group by t.cljds) bb on bb.cljds = aa.cljds
  left join (select t.cljds, sum(t.feiyong) ckbcf
               from emsapp_js_ck_bcf t
              where t.jsrq between to_date('2017-1-1', 'yyyy-mm-dd') and
                    to_date('2017-1-1', 'yyyy-mm-dd')
              group by t.cljds) cc on cc.cljds = aa.cljds
  left join (select t.cljds, sum(t.feiyong) zybcf
               from emsapp_js_zy_bcf t
              where t.jsrq between to_date('2017-1-1', 'yyyy-mm-dd') and
                    to_date('2017-1-1', 'yyyy-mm-dd')
              group by t.cljds) dd on dd.cljds = aa.cljds
  left join (select t.fcz cljds, sum(t.feiyong) hkbcf
               from emsapp_js_hk_bcf t
              where t.jsrq between to_date('2017-1-1', 'yyyy-mm-dd') and
                    to_date('2017-1-1', 'yyyy-mm-dd')
              group by t.fcz) ee on ee.cljds = aa.cljds
 order by aa.cljds

第一個查詢就是最全面的陸運資訊表。