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等是表连接的物理实现方式。

我们先准备一个两个测试表A与B(仅仅是为了演示需要),如下脚本所示

SQL> create table A
2 (
3 name varchar2(12),
4 sex varchar2(6)
5 );

表已创建。

SQL> create table B
2 (
3 name varchar2(12),
4 grade number
5 );

表已创建。

SQL> INSERT INTO A
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行。

SQL> INSERT INTO B
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行。

SQL> commit;

提交完成。

内连接:INNER JOIN

INNER JOIN 它表示返回两个表或记录集连接字段的匹配记录。如下所示,INNER JOIN 可以有二种实现方式:

SQL> select a.name,a.sex,b.grade
2 from a inner join b on a.name = b.name;

NAME SEX GRADE
------------------------ ------------ ----------
kerry male 3
jimmy male 2

SQL> select a.name,a.sex,b.grade
2 from a,b
3 where a.name = b.name;

NAME SEX GRADE
------------------------ ------------ ----------
kerry male 3
jimmy male 2

注意,INNER JOIN可以用使用简写JOIN方式,如下所示,但是建议使用INNER JOIN 而不是JOIN这样的语法。

SQL> SELECT A.NAME, A.SEX,B.GRADE
2 FROM A JOIN B ON A.NAME =B.NAME;

NAME SEX GRADE
------------------------ ------------ ----------
KERRY MALE 3
jimmy male 2

多表内连接:

select *
from (odrm a
inner join custom b on a.fact_no = b.fact_no and a.custom_no = b.custom_no)
inner join stylem c on a.fact_no = c.fact_no and a.style_no = c.style_no;

如果我们用韦恩图来解释INNER JOIN,则非常一目了然、形象生动。可以用下面图来表示

外连接:OUTER JOIN

全连接:full join

全连接 :包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。不符合条件的,以空值代替。如下所示:

SQL> SELECT a.NAME, b.NAME, a.SEX, b.GRADE
2 FROM a FULL OUTER JOIN b ON a.NAME=b.NAME;

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
tina female
wendy female
ken 6
richard 5

已选择6行。

FULL OUTER JOIN的韦恩图如下所示:

左外连接:LEFT JOIN

左外连接又叫左连接 :意思是包含左边表所有记录,右边所有的匹配的记录,如果没有则用空补齐。换句话说就是,列出左边表全部的,及右边表符合条件的,不符合条件的以空值代替。

SQL> SELECT a.NAME, b.NAME, a.SEX, b.GRADE
2 FROM a LEFT OUTER JOIN b ON a.NAME=b.NAME;

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
tina female
WENDY FEMALE

SQL> SELECT a.NAME, b.NAME, a.SEX, b.GRADE
2 FROM A LEFT JOIN B ON A.NAME=B.NAME;

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
TINA FEMALE
wendy female

多表左外连接:

select *
from (odrm a
left outer join custom b on a.fact_no = b.fact_no and a.custom_no = b.custom_no)
left outer join stylem c on a.fact_no = c.fact_no and a.style_no = c.style_no;

在ORACLE 9i以及之前,使用在(+)来表示左连接,哪个带(+)哪个需要条件符合的,另一个全部的。即放左表示右连接,放右表示左连接。

SQL> SELECT A.NAME, B.NAME, A.SEX, B.GRADE
2 FROM A ,B
3 where a.name = b.name(+);

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
tina female
wendy female

SQL>

右外连接:RIGHT JOIN

右外连接又叫右连接: 意思是包括右边表所有记录,匹配左边表的记录,如果没有则以空补齐,换句话说,与左连接一样,列出右边表全部的,及左边表符合条件的,不符合条件的用空值替代。如下所示

SQL> SELECT A.NAME, B.NAME, A.SEX, B.GRADE
2 FROM A RIGHT outer join B ON A.NAME=B.NAME;

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
ken 6
richard 5

SQL> SELECT A.NAME, B.NAME, A.SEX, B.GRADE
2 FROM A RIGHT JOIN B ON A.NAME=B.NAME;

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
ken 6
richard 5

SQL> SELECT A.NAME, B.NAME, A.SEX, B.GRADE
2 FROM A ,B
3 where a.name(+) = b.name;

NAME NAME SEX GRADE
------------------------ ------------------------ ------------ ----------
kerry kerry male 3
jimmy jimmy male 2
ken 6
RICHARD 5

多表右外连接:

select *
from (odrm a
right join custom b on a.fact_no = b.fact_no and a.custom_no = b.custom_no)
right join stylem c on a.fact_no = c.fact_no and a.style_no = c.style_no;

笛卡尔积:CROSS JOIN

CROSS JOIN就是笛卡尔乘积连接,不需要任何关联条件,实现A*B的结果集,其实这种SQL JOIN方式基本上只在理论上有意义,实际当中,很少有用的CORSS JOIN方式。

注意: cross join跟inner join、outer join等有所不同,不需要关键词on,因为它不需要相关字段做关联。

SQL> SELECT a.NAME, a.SEX, b.NAME,b.GRADE
2 FROM A CROSS JOIN B;

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行。

SQL> SELECT A.NAME, A.SEX, B.NAME,B.GRADE
2 FROM a , b;

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行。

注意:笛卡尔积用维恩图是无法体现出来的。

自然连接:NATURAL JOIN

NATURAL JOIN: 在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。如下所示

SQL> SELECT * FROM A NATURAL JOIN B;

NAME SEX GRADE
------------------------ ------------ ----------
kerry male 3
jimmy male 2

有种说法是,对两张表中字段名和数据类型都相同的字段进行等值连接,并返回符合条件的结果 ,其实只要字段名相同,数据类型不同,也可以做NATURAL JOIN,如下所示:

SQL> create table test1(
2 id number(10),
3 name varchar2(12)
4 );

表已创建。

SQL> create table test2(
2 id varchar2(10),
3 nt varchar2(10));

表已创建。

SQL> insert into test1 values(
2 '1000','kk');

已创建 1 行。

SQL> insert into test2 values(
2 '1000','kkkk');

已创建 1 行。

SQL> select * from test1 natural join test2;

ID NAME NT
-------------------- ------------------------ --------------------
1000 kk kkkk

自然连接的两个表的有多个字段都满足有相同名称,那么他们会被作为自然连接的条件,如下案例所示

SQL> drop table test1;

表已删除。

SQL> drop table test2;

表已删除。

SQL> create table test1(
2 id number(10),
3 name varchar2(10));

表已创建。

SQL> create table test2(
2 id number(10),
3 name varchar2(10));

表已创建。

SQL> insert into test1 select 1001, 'ken' from dual union all
2 select 1002,'kk' from dual;

已创建2行。

SQL> insert into test2 select 1001,'ken' from dual union all
2 select 1002,'kkk' from dual;

已创建2行。

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

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

SELECT * ROM 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 

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%';

ORACLE的SQL JOIN方式大全的更多相关文章

  1. ORACLE的SQL JOIN方式小结

    在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图.物化视图等联结),官方的解释如下所示 A join is a query that combines row ...

  2. Oracle 动态sql 实现方式

    /******************************************************************* Sample Program 10: Dynamic SQL ...

  3. Oracle数据库SQL语句操作大全汇总

    数据库各个表空间增长情况的检查: SQL >SELECT A.TABLESPACE_NAME,( 1-(A.TOTAL)/B.TOTAL)* 100 USED_PERCENT FROM (SEL ...

  4. oracle pl/sql的操作大全

    --删除该用户及下面的所有关联 DROP USER fspdrs CASCADE; --创建一个用户 create user fspdrs identified " default tabl ...

  5. Oracle SQL中join方式总结

    在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图.物化视图等联结).SQL JOIN其实是一个逻辑概念,像NEST LOOP JOIN. HASH JOIN等 ...

  6. sql优化 表连接join方式

        sql优化核心 是数据库中 解析器+优化器的工作,我觉得主要有以下几个大方面:1>扫表的方法(索引非索引.主键非主键.书签查.索引下推)2>关联表的方法(三种),关键是内存如何利用 ...

  7. Oracle中的三种Join 方式

    基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort merge join: 将两个表排序,然后再 ...

  8. oracle多表连接方式Hash Join Nested Loop Join Merge Join

    在查看sql执行计划时,我们会发现表的连接方式有多种,本文对表的连接方式进行介绍以便更好看懂执行计划和理解sql执行原理. 一.连接方式:        嵌套循环(Nested  Loops (NL) ...

  9. ORACLE SQL*PLUS 命令大全

    转至:https://www.cnblogs.com/kerrycode/archive/2011/06/09/2076248.html 其实网上已经有SQL*PLUS命令大全这方面的资料了,不过大都 ...

随机推荐

  1. IT兄弟连 JavaWeb教程 监听器2

    4  监听HttpSession域对象的创建和销毁 HttpSessionListener接口用于监听HttpSession对象的创建和销毁. 创建一个Session时,激发sessionCreate ...

  2. Java基础--常用API--日期相关API

    一.java.util.Date 1.只用于显示系统时间,其大部分操作由Calendar代替. 格林威治时间(GMT):指的是1970年1月1日0时,不同地区有时间差. 默认输出格式:星期.月.日.时 ...

  3. 概念端类型“xxx”中的成员“ID”的类型“Edm.Decimal”与对象端类型“xxx”中的成员“ID”的类型“System.Int64”不匹配

    概念端类型“xxx”中的成员“ID”的类型“Edm.Decimal”与对象端类型“xxx”中的成员“ID”的类型“System.Int64”不匹配 使用EF实体模型映射之后将edmx中xml映射关系中 ...

  4. shell脚本编程入门

    Linux的Shell种类众多,这里我们关注的重点是Bash. 基本语法 环境变量$PATH IO重定向:  以<改变标准输入 如:tr -d '\r' < dos-file.txt 以& ...

  5. [Java]HashSet的工作原理

    概述 This class implements the Set interface, backed by a hash table (actually a HashMap instance). It ...

  6. dp优化1——sgq(单调队列)

    该文是对dp的提高(并非是dp入门,dp入门者请先参考其他文章) 有时候dp的复杂度也有点大...会被卡. 这几次blog大多数会讲dp优化. 回归noip2017PJT4.(题目可以自己去百度).就 ...

  7. Codeforces 1167E(思路、数据处理)

    思路 不难想到枚举\(l\),那如何高效求出最小的\(r\)?这样答案加上\(x-r+1\)即可. 如果\(l\)并没在序列里出现--没啥想法:如果\(l\)是序列里的数,我们可以做的事情是记下每个数 ...

  8. vue-cli搭建项目及代理路由设置

    vue-cli 是vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli 一. 安装 node ...

  9. Consul实现服务治理

    .NET Core微服务之基于Consul实现服务治理 https://www.cnblogs.com/edisonchou/p/9124985.html 一.Consul基础介绍 Consul是Ha ...

  10. scau 18087 开始我是拒接的 mobius

    其实有一个很有用的技巧就是,把gcd = 4的贡献,压去gcd = 2时的贡献,就不需要考虑这么多的了. 为什么可以把gcd = 4的,压去gcd = 2的呢,gcd = 12的,压去gcd = 6的 ...