簡體   English   中英

如何在Oracle中使用WITH而不是CONNECT BY來獲取遞歸SQL的深度?

[英]How to get depth of recursive SQL using WITH rather than CONNECT BY in Oracle?

這個簡單的示例表將說明遞歸關系。

CREATE TABLE tree
    (
    key NUMBER(5) NOT NULL PRIMARY KEY,
    name VARCHAR(15) NOT NULL,
    treeHier NUMBER(5)
    );

INSERT INTO tree VALUES('11','Software',NULL);
INSERT INTO tree VALUES('22','OS','11');
INSERT INTO tree VALUES('33','Linux','22');
INSERT INTO tree VALUES('44','Windows','22');
INSERT INTO tree VALUES('55','DB','11');
INSERT INTO tree VALUES('66','Oracle','55');
INSERT INTO tree VALUES('77','MS-SQL','55');

COMMIT;

使用Oracle 12c和許多版本已經存在的功能,我可以使用CONNECT BY和START WITH進行遞歸查詢以獲取所有子節點。

SELECT
    LPAD(' ',LEVEL*2,' ')||' '||
    name||' '||
    key||' '||
    NVL(TO_CHAR(treeHier),'NULL')
FROM
    tree
START WITH
    key = 11
CONNECT BY
    treeHier = PRIOR key
ORDER BY
    key ASC;

偽列LEVEL使得可以知道遞歸的深度並縮進結果。

   Software 11 NULL
     OS 22 11
       Linux 33 22
       Windoze 44 22
     DB 55 11
       Oracle 66 55
       MS-SQL 77 55

7 rows selected.

我相信,從11g開始,Oracle允許編碼人員使用WITH子句創建遞歸查詢。

WITH myRecurse(key,name,treeHier) AS
    (
        SELECT
            tree.key, tree.name, tree.treeHier
        FROM
            tree
        WHERE
            tree.key = 11
    UNION ALL
        SELECT
            tree.key, tree.name, tree.treeHier
        FROM
            tree
        JOIN
            myRecur ON tree.treeHier= myRecurse.key
        ORDER BY
            3 DESC
    )
SELECT
    name||' '||
    key||' '||
    NVL(TO_CHAR(treeHier),'NULL')
FROM
    myRecurse;

但是,LEVEL偽列似乎無法縮進輸出。

Software 11 NULL
OS 22 11
DB 55 11
Linux 33 22
Windoze 44 22
Oracle 66 55
MS-SQL 77 55

7 rows selected.

有沒有使用LEVEL或其他方法的方法,所以我可以使用WITH子句縮進,並獲得類似於CONNECT BY,START WITH方法的輸出?

這是在使用遞歸WITH子句時如何克隆LEVEL偽列(用於縮進)以及分層CONNECT BY查詢的DEPTH FIRST順序的方法。 您可能想看看在遞歸子查詢之后刪除SEARCH ...子句並在末尾刪除ORDER BY子句時會發生什么-看看以什么方式影響輸出。

with r ( lvl, key, name, treehier ) as (
         select  1, key, name, treehier
           from  tree
           where treehier is null
         union all
         select  r.lvl + 1, t.key, t.name, r.key
         from    r join tree t on r.key = t.treehier
       )
       search depth first by name set ord
select   rpad(' ', 2 * (lvl - 1), ' ') || name as name, key, treehier
from     r
order by ord
;

NAME                                  KEY   TREEHIER
------------------------------ ---------- ----------
Software                               11           
  DB                                   55         11
    MS-SQL                             77         55
    Oracle                             66         55
  OS                                   22         11
    Linux                              33         22
    Windows                            44         22

然后,您可以在ORDER BY子句中,在ord之后(幾乎可以肯定不是您想要的!)或在從ORDER BY子句中刪除DESC之后,添加關鍵字DESC(用於降序排序,而不是默認的升序排序)。在SEARCH子句中的name之后。 您將看到在輸出中添加DESC關鍵字的區別。 這些都是將來如有需要的所有選項。 您可能還想通過在SEARCH子句中使用KEY而不是NAME進行試驗-看看會引起什么變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM