Oracle SQL篇(二)oracle自串連操作

來源:互聯網
上載者:User

標籤:

 
   

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;

    EMPNOENAME     JOB             MGRHIREDATE           SAL      COMM    DEPTNO
---------- ---------- --------- ---------- ------------ -------------------- ----------
     7369SMITH     CLERK          790217-DEC-80          800                   20
     7499ALLEN     SALESMAN       769820-FEB-81         1600       300        30
     7521WARD      SALESMAN       769822-FEB-81         1250       500        30
     7566JONES     MANAGER        783902-APR-81         2975                   20
     7654MARTIN    SALESMAN       769828-SEP-81         1250      1400        30
     7698BLAKE     MANAGER        783901-MAY-81         2850                   30
     7782CLARK     MANAGER        783909-JUN-81         2450                   10
     7788SCOTT     ANALYST        756619-APR-87         3000                   20
     7839KING      PRESIDENT           17-NOV-81         5000                   10
     7844TURNER    SALESMAN       769808-SEP-81         1500         0        30
     7876ADAMS     CLERK          778823-MAY-87         1100                   20
     7900JAMES     CLERK          769803-DEC-81          950                   30
     7902FORD      ANALYST        756603-DEC-81         3000                   20
     7934MILLER    CLERK          778223-JAN-82         1300                   10

14 rows selected.

通過觀察發現,在表中資料庫有從屬關係,比如7369smith的經理是7902,7902也是一個員工,名稱是ford,他的經理是7566jones,以此類推,我們最終可以找到公司的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 ‘|| priorename
 2        from emp
 3        start withempno=7839   ---規定遍曆從屬關係樹的起點
 4        connect by priorempno=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 PRIORempno=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 PRIORempno=mgr;

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

---------------------------------------------------------------------------------------
| Id  |Operation                   | Name   | Rows | Bytes | Cost (%CPU)|Time    |
---------------------------------------------------------------------------------------
|   0 | SELECTSTATEMENT            |       |    14|   196|    3   (0)| 00:00:01 |
|*  1 |  CONNECT BY WITHFILTERING  |       |      |      |           |         |
|   2|   TABLE ACCESS BY INDEX ROWID|EMP   |      |      |           |         |
|*  3|    INDEXUNIQUESCAN        | PK_EMP|    1|    4|    0   (0)| 00:00:01 |
|*  4 |   HASHJOIN                 |       |      |      |           |         |
|   5|    CONNECT BYPUMP          |       |      |      |           |         |
|   6|    TABLEACCESSFULL        | EMP   |    14|   196|    3   (0)| 00:00:01 |
|   7|   TABLE ACCESSFULL         | 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  wherew.empno=m.empno(+);

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

---------------------------------------------------------------------------------------
| Id  |Operation                   | Name   | Rows | Bytes | Cost (%CPU)|Time    |
---------------------------------------------------------------------------------------
|   0 | SELECTSTATEMENT            |       |    14|   280|    4   (0)| 00:00:01 |
|   1 |  NESTEDLOOPSOUTER         |       |    14|   280|    4   (0)| 00:00:01 |
|   2|   TABLE ACCESSFULL         | EMP   |    14|   140|    3   (0)| 00:00:01 |
|   3|   TABLE ACCESS BY INDEX ROWID|EMP   |    1 |    10|    1   (0)| 00:00:01 |
|*  4|    INDEXUNIQUESCAN        | PK_EMP|    1|      |    0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

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

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


通過上面的例子我們可以發現,層次查詢的速度也要快於自串連操作,當然了,我們在這裡的討論,並沒有考慮兩種語句對其他資源的影響。

Oracle SQL篇(二)oracle自串連操作

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.