Oracle SQL篇(二)oracle自连接操作

   

oracle 的自连接(self join)操作

对于oracle数据库来说,目前支持两套语法,一套是oracle自己的sql语法,一套是通行标准的SQL99语法,那么对于oracle的连接操作
来说,也完全可以使用这样的两套语法来分别的实现。当然从效率上来说,两者是没有差别的。只不过从我的角度来讲,oracle的语法更加简洁而已。

比如说我们有一张表emp,表里数据如下
[email protected]> conn scott/tiger
Connected.
[email protected]>

set linesize 120
[email protected]> set pagesize 100
[email protected]> select * from emp;

EMPNO
ENAME     
JOB             
MGR
HIREDATE           
SAL      
COMM    
DEPTNO
---------- ---------- --------- ---------- ------------ ----------
---------- ----------
     
7369
SMITH     
CLERK          
7902
17-DEC-80          
800                   
20
     
7499
ALLEN     
SALESMAN       
7698
20-FEB-81         
1600       
300        
30
     
7521
WARD      
SALESMAN       
7698
22-FEB-81         
1250       
500        
30
     
7566
JONES     
MANAGER        
7839
02-APR-81         
2975                   
20
     
7654
MARTIN    
SALESMAN       
7698
28-SEP-81         
1250      
1400        
30
     
7698
BLAKE     
MANAGER        
7839
01-MAY-81         
2850                   
30
     
7782
CLARK     
MANAGER        
7839
09-JUN-81         
2450                   
10
     
7788
SCOTT     
ANALYST        
7566
19-APR-87         
3000                   
20
     
7839
KING      
PRESIDENT           
17-NOV-81         
5000                   
10
     
7844
TURNER    
SALESMAN       
7698
08-SEP-81         
1500         
0        
30
     
7876
ADAMS     
CLERK          
7788
23-MAY-87         
1100                   
20
     
7900
JAMES     
CLERK          
7698
03-DEC-81          
950                   
30
     
7902
FORD      
ANALYST        
7566
03-DEC-81         
3000                   
20
     
7934
MILLER    
CLERK          
7782
23-JAN-82         
1300                   
10

14 rows selected.

通过观察发现,在表中数据库有从属关系,比如7369
smith的经理是7902,7902也是一个员工,名称是ford,他的经理是7566
jones,以此类推,我们最终可以找到公司的boss 7839 king。
现在我的需求是,找到公司里的上下级对应关系,我们分别用oracle的语法和sql99的语法来实现,我们可以得到同样的结果

oracle语法:我们注意到from后面
表emp出现两次,并且使用了不同的别名,也就是表自己和自己来关联,所以我们称这样的连接为自连接操作。当然了,以下的例子中使用了外连接操作,我以后会单独的说明。

[email protected]> select w.ename||‘ report for ‘ ||m.ename
"Relations"
 
2        
from emp w,emp m
 
3        
where w.empno=m.empno(+);

Relations
--------------------------------
SMITH report for SMITH
ALLEN report for ALLEN
WARD report for WARD
JONES report for JONES
MARTIN report for MARTIN
BLAKE report for BLAKE
CLARK report for CLARK
SCOTT report for SCOTT
KING report for KING
TURNER report for TURNER
ADAMS report for ADAMS
JAMES report for JAMES
FORD report for FORD
MILLER report for MILLER

14 rows selected.

sql99语法:join on 语法的实现
[email protected]> select w.ename||‘ report for ‘ ||m.ename
"Relations"
 
2        
from emp w left outer join emp m
 
3        
on (w.mgr=m.empno);

Relations
--------------------------------
SMITH report for FORD
ALLEN report for BLAKE
WARD report for BLAKE
JONES report for KING
MARTIN report for BLAKE
BLAKE report for KING
CLARK report for KING
SCOTT report for JONES
KING report for
TURNER report for BLAKE
ADAMS report for SCOTT
JAMES report for BLAKE
FORD report for JONES
MILLER report for CLARK

14 rows selected.

其实,oracle对于处理表中有从属关系的记录,提供了一种查询方法,我们称之为层次查询,来看一个例子

[email protected]> select ename ||‘ report for ‘|| prior
ename
 
2        
from emp
 
3        
start with
empno=7839   
---规定遍历从属关系树的起点
 
4        
connect by prior
empno=mgr;   
----规定了遍历的方向

ENAME||‘REPORTFOR‘||PRIORENAME
--------------------------------
KING report for
JONES report for KING
SCOTT report for JONES
ADAMS report for SCOTT
FORD report for JONES
SMITH report for FORD
BLAKE report for KING
ALLEN report for BLAKE
WARD report for BLAKE
MARTIN report for BLAKE
TURNER report for BLAKE
JAMES report for BLAKE
CLARK report for KING
MILLER report for CLARK
14 rows selected.

为了使查询的结果更具有可读性,我们借助一个函数SYS_CONNECT_BY_PATH来做一下处理,来看结果:
[email protected]> SELECT LPAD(‘ ‘,
2*level-1)||SYS_CONNECT_BY_PATH(ename, ‘/‘) "Path"
  2  FROM emp
  3  START WITH empno =
7839
  4  CONNECT BY PRIOR
empno=mgr;

Path
-------------------------------------------------------------------------------

/KING
   /KING/JONES
    
/KING/JONES/SCOTT
      
/KING/JONES/SCOTT/ADAMS
    
/KING/JONES/FORD
      
/KING/JONES/FORD/SMITH
   /KING/BLAKE
    
/KING/BLAKE/ALLEN
    
/KING/BLAKE/WARD
    
/KING/BLAKE/MARTIN
    
/KING/BLAKE/TURNER
    
/KING/BLAKE/JAMES
   /KING/CLARK
    
/KING/CLARK/MILLER

14 rows selected.

通过上面的结果,你是否发现,从属关系更加清晰,也更加直观呢。

当然了对于我们来讲,好看的格式化的输出只是锦上添花,更重要的是语句的执行的速度,也就是性能的考虑
借助于autotrace工具,我们来看语句的执行计划

[email protected]> set autotrace trace exp
[email protected]>
[email protected]> SELECT LPAD(‘ ‘,
2*level-1)||SYS_CONNECT_BY_PATH(ename, ‘/‘) "Path"
  2  FROM emp
  3  START WITH empno =
7839
  4  CONNECT BY PRIOR
empno=mgr;

Execution Plan
----------------------------------------------------------
Plan hash value: 3613731379

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

| Id  |
Operation                   
| Name   | Rows 
| Bytes | Cost (%CPU)|
Time    
|
---------------------------------------------------------------------------------------

|   0 | SELECT
STATEMENT            
|       
|    14
|   196
|    
3   (0)| 00:00:01 |
|*  1 |  CONNECT BY WITH
FILTERING  
|       
|      
|      
|           
|         
|
|   2
|   TABLE ACCESS BY INDEX ROWID|
EMP   
|      
|      
|           
|         
|
|*  3
|    INDEX
UNIQUE
SCAN        
| PK_EMP
|    
1
|    
4
|    
0   (0)| 00:00:01 |
|*  4 |   HASH
JOIN                 
|       
|      
|      
|           
|         
|
|   5
|    CONNECT BY
PUMP          
|       
|      
|      
|           
|         
|
|   6
|    TABLE
ACCESS
FULL        
| EMP   
|    14
|   196
|    
3   (0)| 00:00:01 |
|   7
|   TABLE ACCESS
FULL         
| EMP   
|    14
|   196
|    
3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("EMPNO"=7839)
   3 - access("EMPNO"=7839)
   4 - access("MGR"=NULL)

[email protected]> select w.ename||‘ report for ‘ ||m.ename
"Relations"
  2  from emp w,emp m
  3  where
w.empno=m.empno(+);

Execution Plan
----------------------------------------------------------
Plan hash value: 2199491010

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

| Id  |
Operation                   
| Name   | Rows 
| Bytes | Cost (%CPU)|
Time    
|
---------------------------------------------------------------------------------------

|   0 | SELECT
STATEMENT            
|       
|    14
|   280
|    
4   (0)| 00:00:01 |
|   1 |  NESTED
LOOPS
OUTER         
|       
|    14
|   280
|    
4   (0)| 00:00:01 |
|   2
|   TABLE ACCESS
FULL         
| EMP   
|    14
|   140
|    
3   (0)| 00:00:01 |
|   3
|   TABLE ACCESS BY INDEX ROWID|
EMP   
|    
1 |    10
|    
1   (0)| 00:00:01 |
|*  4
|    INDEX
UNIQUE
SCAN        
| PK_EMP
|    
1
|      
|    
0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

4 -
access("W"."EMPNO"="M"."EMPNO"(+))

通过上面的例子我们可以发现,层次查询的速度也要快于自连接操作,当然了,我们在这里的讨论,并没有考虑两种语句对其他资源的影响。

时间: 2024-08-07 21:20:22

Oracle SQL篇(二)oracle自连接操作的相关文章

Oracle SQL篇(一)null值之初体验

    从我第一次正式的写sql语句到现在,已经超过10年的时间了.我写报表,做统计分析和财务对账,我一点点的接触oracle数据库,并尝试深入了解.这条路,一走就是10年,从充满热情,到开始厌倦,我不知道我还能坚持多久,未来的路,谁知道呢? 也许是该抓紧时间,做一点什么了,我不知道该开始写些什么,我从来没有在网上写东西的习惯.     先从简单的开始吧,那当然就是SQL,这是我SQL系列的第一篇,希望我能够坚持. 在Oracle数据库中,如果一个表中的列没有值的话,我们可以说是空值,比如IT员

Oracle SQL篇(四)group by 分组与分组的加强 rollup

    分组操作group by 和分组的强化(rollup) 分组操作和分组函数的使用,对于编写SQL语句的人来说,是最基本的概念. 我们来看下面的例子: 在这里我们使用员工表EMP [email protected]> select * from emp; EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO ---------- ---------- ------

oracle学习篇六:更新操作、事务处理

----------------1.数据库更新操作----------------------------- select * from tab;--查询表 drop table siebel_user;--删除表 --copy一份表结构create table myemp as select * from emp; select * from myemp; --插入记录insert into myemp(empno,ename,job,hiredate,sal,comm,deptno) val

Oracle Sql Developer 连接oracle

PL/Sql 初次使用需要配置文件内容,对于我这种Oracle新手来说各种配置有点凌乱,所以果断选择Sql Developer. 选择它是因为初次使用的时候它不用想PL/Sql那样配置文件,而只需要添加一个连接即可.如图 Sql Developer除了能连接Oracle还可以连接SqlServer

oracle sql 创建表格 oracle建表设置主键自增

1.新建table CREATE TABLE ysb_log( id number(8) primary key not null , tbdate varchar(50) NULL, tb_time varchar(50) NOT NULL, tblog varchar(500) NOT NULL, tbreor varchar2(20) null, bs varchar(50) NOT NULL ); 在Oracle中sequence就是所谓的序列号,每次取的时候它会自动增加,一般用在需要按

Oracle SQL Developer调试Oracle存储过程

1.首先你编译通过你的存储过程,编译的时候一定要选"编译以进行调试". 2.在想要调试的行上设置好断点. 3.点击"调试"按钮,然后输入存储过程入参,点"确定"开始调试. 4.断点进入后,上方会出现一排调试按钮,并且鼠标移上变量也会自动显示变量的类型和值. 5.你也可以选中变量后右键点"检查"在弹出窗口中显示变量的值,或者点"监测"在下方的窗口中一直观察变量的值变化,或者点"运行至光标处"

Oracle SQL tuning 步骤

Oracle SQL tuning 步骤 SQL是的全称是Structured Query Language(结构化查询语言).SQL是一个在80年代中期被使用的工业标准数据库查询语言.不要把SQL语言与商业化产品如Microsoft SQL server或开源产品MySQL相混淆.所有的使用SQL缩略词的这些都是SQL标准的一部分. 一.SQL tuning之前的调整    下面这个粗略的方法能够节省数千小时乏味的SQL tuning,因为一旦调整它将影响数以百计的SQL查询.记住,你必须优先

使用Oracle SQL Developer迁移MySQL至Oracle数据库

Oracle SQL Developer是Oracle官方出品的数据库管理工具.本文使用Oracle SQL Developer执行从MySQL迁移至Oracle数据库的操作. 2017年3月6日 操作步骤: 1.在Oracle数据库中创建移植资料档案库用户 资料档案库用户不是用来接收MySQL迁移数据的用户,而是进行数据迁移配置的用户. Oracle创建用户命令如下: create user migrater identified by migrater; alter user migrate

用oracle SQL Developer 进行数据库数据复制

最近因为工作需要,被老板要求把服务器上的oracle数据库的数据迁移到另一台服务器上,自己对oracle不是很熟悉,迁移数据库这个事情很是花费了些时间,也在网上查询过很多资料. 各种招式用尽还是不能成功迁移. 最后本着死马当活马医的心态,对 oracle SQL Developer 进行一顿操作后发现,完全不需要什么各种命令操作,用oracle SQL Developer 可以非常方便的解决问题. 我就以最新的oracle12c为例子: 1: 首先,你需要再oracle官网上下载oracle的客