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

第一个查询就是最全面的陆运信息表。


  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值