ORACLE的SQL JOIN方式小结
在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等是表连接的物理实现方式。
我们先准备一个两个测试表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 3
jimmy 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 3
jimmy male 2
第三种方式,使用USING,如下所示,这种写法一般较少人使用。
SQL> SELECT NAME, M.SEX,N.GRADE
2 FROM M INNER JOIN N USING(NAME);
NAME SEX GRADE
------------ ------ ----------
kerry male 3
jimmy male 2
SQL>
注意,INNER JOIN可以用使用简写JOIN方式,如下所示,但是建议使用INNER JOIN 而不是JOIN这样的语法。
如果我们用韦恩图来解释INNER JOIN,则非常一目了然、形象生动。可以用下面图来表示(此图以及下面的韦恩图均来自链接http://pafumi.net/SQL_Joins.html ,本来想自己画,无奈有些图使用word不好实现,R语言不会。故在此借其图用用)
外连接: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 3
jimmy jimmy male 2
ken 6
richard 5
tina female
wendy female
6 rows selected.
FULL OUTER JOIN的韦恩图如下所示:
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 3
jimmy jimmy male 2
tina female
wendy 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 3
jimmy jimmy male 2
tina female
wendy 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 3
jimmy jimmy male 2
tina female
wendy female
SQL>
LEFT OUTER JOIN的韦恩图如下所示:
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 3
jimmy 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 3
jimmy 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 3
jimmy jimmy male 2
ken 6
richard 5
笛卡尔积: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 3
kerry male jimmy 2
kerry male ken 6
kerry male richard 5
jimmy male kerry 3
jimmy male jimmy 2
jimmy male ken 6
jimmy male richard 5
tina female kerry 3
tina female jimmy 2
tina female ken 6
NAME SEX NAME GRADE
------------ ------ ------------ ----------
tina female richard 5
wendy female kerry 3
wendy female jimmy 2
wendy female ken 6
wendy female richard 5
16 rows selected.
注意:笛卡尔积用维恩图是无法体现出来的。
自然连接:NATURAL JOIN
NATURAL JOIN: 在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。如下所示
SQL> SELECT * FROM M NATURAL JOIN N;
NAME SEX GRADE
------------ ------ ----------
kerry male 3
jimmy 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>
自然连接的两个表的有多个字段都满足有相同名称,那么他们会被作为自然连接的条件,如下案例所示
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
NATURAL JOIN的韦恩图,其实和内连接是一样的。如下所示:
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
ORACLE的SQL JOIN方式小结的更多相关文章
- ORACLE的SQL JOIN方式大全
ORACLE的SQL JOIN方式大全 在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图.物化视图等联结),官方的解释如下所示 A join is a que ...
- Oracle 动态sql 实现方式
/******************************************************************* Sample Program 10: Dynamic SQL ...
- Oracle SQL中join方式总结
在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图.物化视图等联结).SQL JOIN其实是一个逻辑概念,像NEST LOOP JOIN. HASH JOIN等 ...
- sql优化 表连接join方式
sql优化核心 是数据库中 解析器+优化器的工作,我觉得主要有以下几个大方面:1>扫表的方法(索引非索引.主键非主键.书签查.索引下推)2>关联表的方法(三种),关键是内存如何利用 ...
- Oracle中的三种Join 方式
基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort merge join: 将两个表排序,然后再 ...
- oracle多表连接方式Hash Join Nested Loop Join Merge Join
在查看sql执行计划时,我们会发现表的连接方式有多种,本文对表的连接方式进行介绍以便更好看懂执行计划和理解sql执行原理. 一.连接方式: 嵌套循环(Nested Loops (NL) ...
- SQL Server Join方式
原文:SQL Server Join方式 0.参考文献 Microsoft SQL Server企业级平台管理实践 看懂SqlServer查询计划 1.测试数据准备 参考:Sql Server中的表访 ...
- Oracle查看SQL执行计划的方式
Oracle查看SQL执行计划的方式 获取Oracle sql执行计划并查看执行计划,是掌握和判断数据库性能的基本技巧.下面案例介绍了多种查看sql执行计划的方式: 基本有以下几种方式: ...
- Spark SQL join的三种实现方式
引言 join是SQL中的常用操作,良好的表结构能够将数据分散到不同的表中,使其符合某种规范(mysql三大范式),可以最大程度的减少数据冗余,更新容错等,而建立表和表之间关系的最佳方式就是join操 ...
随机推荐
- 浅谈 php 采用curl 函数库获取网页 cookie 和 带着cookie去访问 网页的方法!!!!
由于近段时间帮朋友开发一个能够查询正方教务系统的微信公众平台号.有所收获.这里总结下个人经验. 开讲前,先吐槽一下新浪云服务器,一个程序里的 同一个函数 在PC测试可以正常运行,在它那里就会挂的 ...
- (二十)WebGIS中图层树功能的设计和实现
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在GIS的桌面工具中,比如arcgis desktop或者S ...
- 理解JAVASCRIPT 闭包
最近去面试了一家企业,结果非常灰心丧气,于是周末给自己定了一个目标 学好一门,学精通一门.不求多,只求懂. 最近看到一个概念“闭包”. 什么是闭包呢? 简单一点就是:看得到多和看得到少的区别. 上面这 ...
- KVM的前世今生
1.虚拟化技术的演变过程:软件模拟.虚拟化层翻译.容器虚拟化三个阶段 (1)软件模拟的技术方式 软件模拟是通过软件完全模拟CPU.网卡.芯片组.磁盘等计算机硬件,因为是软件模拟,所以理论上可以模拟任何 ...
- 根据起止日期构建指定查询条件:第N周(yyyy-MM-dd/yyyy-MM-dd)
项目中有个查询模块中用到查询条件: 年和周. 以往我直接指定是第几周,后来测试反映如果直接选择周的话并不知道所选周代表的年月日,而无法最快查询数据,后更改查询条件如下: 指定一个起始年月,根据起始年月 ...
- CSS魔法堂:重拾Border之——解构Border
前言 当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...
- 原生AJAX入门讲解(含实例)
相对于jQuery.YUI以及其他一些类库的AJAX封装,原生JS的AJAX显得那么的尴尬,兼容性不好,要记很多的方法属性,调用不便捷,代码臃肿...但我还是想说,原生JS才是最根本最底层的知识(虽然 ...
- Chrome 控制台实用指南
前言 个人博客:Damonare的个人主页 Chrome浏览器我想是每一个前端er必用工具之一吧,一部分原因是它速度快,体积不大,支持的新特性也比其它浏览器多,还有一部分我想就是因为它的控制台功能强大 ...
- .net winform的IsMdiContainer属性
.net winform的IsMdiContainer属性 获取或设置一个值,该值指示窗体是否为多文档界面 (MDI) 子窗体的容器. 当你想让某个窗体成为其他窗体的父窗体时,请先把窗体的IsMdiC ...
- Web 上传图片加水印
上传图片加水印 需要使用控件FileUpload 上传按钮Image控件展示上传的图片,页面中拖入三个控件 <form id="form1" runat="serv ...












