设为首页 收藏本站
查看: 1042|回复: 0

[经验分享] ORACLE的SQL JOIN方式小结

[复制链接]

尚未签到

发表于 2017-7-14 14:16:56 | 显示全部楼层 |阅读模式
  在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图、物化视图等联结),官方的解释如下所示
  
  A join is a query that combines rows from two or more tables, views, or materialized views. Oracle Database performs a join whenever multiple tables appear in the FROM clause of the query. The select list of the query can select any columns from any of these tables. If any two of these tables have a column name in common, then you must qualify all references to these columns throughout the query with table names to avoid ambiguity.
  
  SQL JOIN 归纳起来有下面几种方式,下面一起来梳理一下这些概念。SQL JOIN其实是一个逻辑概念,像NEST LOOP JOIN、 HASH JOIN等是表连接的物理实现方式。
  
   DSC0000.png   
  我们先准备一个两个测试表M与N(仅仅是为了演示需要),如下脚本所示


SQL> CREATE TABLE M  2  (  3       NAME       VARCHAR2(12)  4      ,SEX        VARCHAR2(6)  5  ); Table created. SQL> CREATE TABLE N  2  (  3         NAME       VARCHAR2(12)  4      ,GRADE      NUMBER(2)  5  ); Table created. SQL> INSERT INTO M  2  SELECT 'kerry', 'male'   FROM DUAL UNION ALL  3  SELECT 'jimmy', 'male'   FROM DUAL UNION ALL  4  SELECT 'tina' , 'female' FROM DUAL UNION ALL  5  SELECT 'wendy', 'female' FROM DUAL; 4 rows created. SQL> COMMIT; Commit complete. SQL> INSERT INTO N  2  SELECT 'kerry',  3 FROM DUAL UNION ALL  3  SELECT 'jimmy',  2 FROM DUAL UNION ALL  4  SELECT 'ken'  ,  6 FROM DUAL UNION ALL  5  SELECT 'richard',5 FROM DUAL; 4 rows created. SQL> COMMIT; Commit complete.
  
  内连接:INNER JOIN
    INNER JOIN 它表示返回两个表或记录集连接字段的匹配记录。如下所示,INNER JOIN 可以有三种实现方式:




SQL> SELECT M.NAME, M.SEX, N.GRADE   2  FROM M INNER JOIN N ON M.NAME=N.NAME; NAME         SEX         GRADE------------ ------ ----------kerry        male            3jimmy        male            2 SQL> SELECT M.NAME, M.SEX, N.GRADE  2  FROM M, N   3  WHERE M.NAME=N.NAME; NAME         SEX         GRADE------------ ------ ----------kerry        male            3jimmy        male            2  
  第三种方式,使用USING,如下所示,这种写法一般较少人使用。




SQL> SELECT NAME, M.SEX,N.GRADE  2  FROM M INNER JOIN N USING(NAME); NAME         SEX         GRADE------------ ------ ----------kerry        male            3jimmy        male            2 SQL>
   DSC0001.png
  
  注意,INNER JOIN可以用使用简写JOIN方式,如下所示,但是建议使用INNER JOIN 而不是JOIN这样的语法。
  
   DSC0002.png
  
  如果我们用韦恩图来解释INNER JOIN,则非常一目了然、形象生动。可以用下面图来表示(此图以及下面的韦恩图均来自链接http://pafumi.net/SQL_Joins.html ,本来想自己画,无奈有些图使用word不好实现,R语言不会。故在此借其图用用)
  
   DSC0003.png
  
  
  
  外连接:OUTER JOIN
  
  
  1 全连接:full join
  
    全连接 :包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。不符合条件的,以空值代替。如下所示:




SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M FULL OUTER JOIN N ON M.NAME=N.NAME; NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2             ken                          6             richard                      5tina                      femalewendy                     female 6 rows selected.
   DSC0004.png
  
  FULL OUTER JOIN的韦恩图如下所示:
  
   DSC0005.png
  
  
  2 左外连接:LEFT JOIN  
  左外连接又叫左连接 :意思是包含左边表所有记录,右边所有的匹配的记录,如果没有则用空补齐。换句话说就是,列出左边表全部的,及右边表符合条件的,不符合条件的以空值代替。




SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M LEFT OUTER JOIN N ON M.NAME=N.NAME; NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2tina                      femalewendy                     female SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M LEFT JOIN N ON M.NAME=N.NAME; NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2tina                      femalewendy                     female  
  在ORACLE 9i以及之前,使用在(+)来表示左连接,哪个带(+)哪个需要条件符合的,另一个全部的。即放左表示右连接,放右表示左连接。这种写法,如果不熟悉,就会有点陌生。其实也不是什么新鲜事物,只是你不太熟悉而已。




SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M, N  3  WHERE M.NAME=N.NAME(+); NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2tina                      femalewendy                     femaleSQL>
   DSC0006.png
  
  LEFT OUTER JOIN的韦恩图如下所示:
   DSC0007.png
  
  
  3 右外连接:RIGHT JOIN   
  右外连接又叫右连接: 意思是包括右边表所有记录,匹配左边表的记录,如果没有则以空补齐,换句话说,与左连接一样,列出右边表全部的,及左边表符合条件的,不符合条件的用空值替代。如下所示




SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M RIGHT OUTER JOIN N ON M.NAME=N.NAME; NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2             ken                          6             richard                      5 SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M RIGHT JOIN N ON M.NAME=N.NAME; NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2             ken                          6             richard                      5 SQL> SELECT M.NAME, N.NAME, M.SEX, N.GRADE  2  FROM M, N  3  WHERE M.NAME(+) = N.NAME; NAME         NAME         SEX         GRADE------------ ------------ ------ ----------kerry        kerry        male            3jimmy        jimmy        male            2             ken                          6             richard                      5
   DSC0008.png
  
  
  笛卡尔积:CROSS JOIN
  
  CROSS JOIN就是笛卡尔乘积连接,不需要任何关联条件,实现M*N的结果集,其实这种SQL JOIN方式基本上只在理论上有意义,实际当中,很少有用的CORSS JOIN方式。  注意: cross join跟inner join、outer join等有所不同,不需要关键词on,因为它不需要相关字段做关联。




SQL> SELECT M.NAME, M.SEX, N.NAME,N.GRADE  2  FROM M CROSS JOIN N; NAME         SEX    NAME              GRADE------------ ------ ------------ ----------kerry        male   kerry                 3kerry        male   jimmy                 2kerry        male   ken                   6kerry        male   richard               5jimmy        male   kerry                 3jimmy        male   jimmy                 2jimmy        male   ken                   6jimmy        male   richard               5tina         female kerry                 3tina         female jimmy                 2tina         female ken                   6 NAME         SEX    NAME              GRADE------------ ------ ------------ ----------tina         female richard               5wendy        female kerry                 3wendy        female jimmy                 2wendy        female ken                   6wendy        female richard               5 16 rows selected.
   DSC0009.png
  注意:笛卡尔积用维恩图是无法体现出来的。
  
  自然连接:NATURAL JOIN
    NATURAL JOIN: 在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。如下所示




SQL> SELECT * FROM M NATURAL JOIN N; NAME         SEX         GRADE------------ ------ ----------kerry        male            3jimmy        male            2
  官方解释:
  The NATURAL keyword indicates that a natural join is being performed. A natural join is based on all columns in the two tables that have the same name. It selects rows from the two tables that have equal values in the relevant columns. When specifying columns that are involved in the natural join, do not qualify the column name with a table name or table alias
    有种说法是,对两张表中字段名和数据类型都相同的字段进行等值连接,并返回符合条件的结果 ,其实只要字段名相同,数据类型不同,也可以做NATURAL JOIN,如下所示:




SQL> CREATE TABLE TEST1  2  (           3     ID     NUMBER(10),  4     NAME   VARCHAR2(12)  5  ); Table created. SQL>  CREATE TABLE TEST2  2  (  3    ID    VARCHAR2(10),  4     NT    VARCHAR2(12)  5  ); Table created. SQL> INSERT INTO TEST1  2  VALUES(1000, 'KERRY'); 1 row created. SQL> COMMIT; Commit complete. SQL> INSERT INTO TEST2  2  VALUES('1000', 'KKK'); 1 row created. SQL> SELECT * FROM TEST1 NATURAL JOIN TEST2; ID         NAME         NT---------- ------------ ------------1000       KERRY        KKK SQL>
   DSC00010.png
    自然连接的两个表的有多个字段都满足有相同名称,那么他们会被作为自然连接的条件,如下案例所示




SQL> DROP TABLE TEST1; Table dropped. SQL> DROP TABLE TEST2; Table dropped. SQL> CREATE TABLE TEST1  2  (  3     ID     NUMBER(10),  4     NAME   VARCHAR2(12)  5  )  6  ; Table created. SQL> CREATE TABLE TEST2  2  (  3    ID    NUMBER(10),  4    NAME  VARCHAR2(12)  5  ); Table created. SQL> INSERT INTO TEST1  2  SELECT 1000, 'KERRY' FROM DUAL UNION ALL  3  SELECT 1001, 'KEN'   FROM DUAL; 2 rows created. SQL> COMMIT; Commit complete. SQL> INSERT INTO TEST2  2  SELECT 1000, 'KKK' FROM DUAL UNION ALL  3  SELECT 1001, 'KEN' FROM DUAL; 2 rows created. SQL> COMMIT; Commit complete. SQL> SELECT * FROM TEST1 NATURAL JOIN TEST2;         ID NAME---------- ------------      1001 KEN
   DSC00011.png
  
  NATURAL JOIN的韦恩图,其实和内连接是一样的。如下所示:
   DSC00012.png
    
SEMI JOIN


  SEMI JOIN 多在子查询exists中使用,对外部row source的每个键值,查找到内部row source匹配的第一个键值后就返回,如果找到就不用再查找内部row source其他的键值了。官方介绍案例如下


Using Semijoins: Example


In the following example, only one row needs to be returned from the departments table, even though many rows in the employees table might match the subquery. If no index has been defined on thesalary column in employees, then a semijoin can be used to improve query performance.


SELECT * FROM departments


   WHERE EXISTS


   (SELECT * FROM employees


       WHERE departments.department_id = employees.department_id


       AND employees.salary > 2500)


   ORDER BY department_name;



ANTI JOIN


ANTI JOIN多用于!=或not in 等查询;如果找到满足条件(!= not in)的不返回,不满足条件(!= not in)的返回。和join相反。



Using Antijoins: Example


The following example selects a list of employees who are not in a particular set of departments:


SELECT * FROM employees


   WHERE department_id NOT IN


   (SELECT department_id FROM departments


       WHERE location_id = 1700)


   ORDER BY last_name;




SELF JOIN


SELF JOIN其实就是某个表和其自身连接,连接方式可以是内连接,外连接,交叉连接



Using Self Joins: Example  


The following query uses a self join to return the name of each employee along with the name of the employee's manager. A WHERE clause is added to shorten the output.


SELECT e1.last_name||' works for '||e2.last_name


   "Employees and Their Managers"


   FROM employees e1, employees e2


   WHERE e1.manager_id = e2.employee_id


      AND e1.last_name LIKE 'R%';





Employees and Their Managers   


-------------------------------


Rajs works for Mourgos

Raphaely works for King

Rogers works for Kaufling

Russell works for King


  
  参考资料:
  https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm
  http://pafumi.net/SQL_Joins.html
  http://www.itpub.net/thread-420946-1-1.html
  
    

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-393781-1-1.html 上篇帖子: 撸一段 SQL ? 还是撸一段代码? 下篇帖子: sql server concat()函数
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表