如何在分层查询中删除不以叶节点结尾的列

时间:2014-04-13 15:46:45

标签: oracle oracle11g

如何在分层查询中删除不以叶节点结尾的列。可能有人共享示例

SELECT cust_id AS child_id
           FROM customer
          WHERE LEVEL = v_cnt
          START WITH cust_id = 12660
         CONNECT BY PRIOR cust_id = cust_cust_id

我为此编写了一个存储过程。

CREATE OR REPLACE PROCEDURE FRONTROOM.SP_CUST_HIER_DENORM_2

IS 
L_ERR_MSG VARCHAR2(1000);
l_cust_id number(10);
v_cnt number(1);
BEGIN
SP_LOG_ENTRY(CURRENT_TIMESTAMP,'SP_CUST_HIER_DENORM_2','START',NULL,NULL,NULL);

-- select cust_id into l_cust_id from customer where true_gcdb_source_key ='9900000001';


    delete CUST_HIER_DNORM_2;

    for v_cnt in 2..6
    loop


   -- v_cnt := 6;                
     For j in (  SELECT cust_id AS child_id
           FROM customer
          WHERE LEVEL = v_cnt
          START WITH cust_id = 12660
         CONNECT BY PRIOR cust_id = cust_cust_id)

     LOOP
     begin

            INSERT INTO CUST_HIER_DNORM_2
                (LVL_1,LVL_2,LVL_3,LVL_4,LVL_5,LVL_6,LVL_7,LVL_8 )
               SELECT SUM(DECODE(LEVEL,v_cnt,cust_id))  LVL_1 ,
                      SUM(DECODE(LEVEL,v_cnt-1,cust_id))  LVL_2 ,
                      SUM(DECODE(LEVEL,v_cnt-2,cust_id))  LVL_3 ,
                      SUM(DECODE(LEVEL,v_cnt-3,cust_id))  LVL_4 ,
                      SUM(DECODE(LEVEL,v_cnt-4,cust_id))  LVL_5 ,
                      SUM(DECODE(LEVEL,v_cnt-5,cust_id))  LVL_6 ,
                      SUM(DECODE(LEVEL,v_cnt-6,cust_id))  LVL_7 ,
                      SUM(DECODE(LEVEL,v_cnt-7,cust_id))  LVL_8 
              FROM CUSTOMER 
              WHERE LEVEL <=v_cnt
              START WITH cust_id = j.child_id  
              CONNECT BY  cust_id = PRIOR cust_cust_id ;
        EXCEPTION
        WHEN OTHERS
        THEN
        SP_LOG_ENTRY (CURRENT_TIMESTAMP,
               'SP_CUST_HIER_DENORM_2',
               'ERROR WHILE INSERTING ',
               SQLERRM,
               '* ' || j.CHILD_ID  || ' *',NULL

            );
       END;
   END LOOP ;
  end loop;

   COMMIT;



UPDATE cust_hier_dnorm_2 cd
   SET LVL_1_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_1 = C.CUST_ID ),
       LVL_2_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_2 = C.CUST_ID ),
       LVL_3_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_3 = C.CUST_ID ),
       LVL_4_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_4 = C.CUST_ID ),
       LVL_5_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_5 = C.CUST_ID ),
       LVL_6_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_6 = C.CUST_ID  ),
       LVL_7_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_7 = C.CUST_ID ),
       LVL_8_DESC =
          (SELECT c.true_gcdb_source_key
             FROM customer c
            WHERE cd.lvl_8 = C.CUST_ID );

commit;


   SP_LOG_ENTRY(CURRENT_TIMESTAMP,'SP_CUST_HIER_DENORM_2','START',NULL,NULL,NULL);

   EXCEPTION
   WHEN OTHERS THEN
   L_ERR_MSG :=SQLERRM;
   SP_LOG_ENTRY(CURRENT_TIMESTAMP,'SP_LOAD_CUST_HIER_DENORM_2',NULL,L_ERR_MSG,NULL,NULL);
   END;
/

目前我的输出采用这种格式

lvl 1        lvl2    lvl3    lvl4    lvl5    lvl6
12660   12389   12517   12476   12557   3953(leaf node)
12660   12389   12517   12476   12557   3978(leaf node)
12660   12389   12517   12476   12557   3992(leaf node)
12660   12389   12517   12476   12557   
12660   12389   12517   12476   
12660   12389   12517   


desired output
lvl 1         lvl2     lvl3 lvl4      lvl5   lvl6
12660   12389   12517   12476   12557   3953(leaf node)
12660   12389   12517   12476   12557   3978(leaf node)
12660   12389   12517   12476   12557   3992(leaf node)

表示删除不以叶节点结尾的列。

它是一个denorm table.all将所有记录插入到非规范化表中

1 个答案:

答案 0 :(得分:0)

目前还不太清楚你想要得到什么。如果要仅提取叶节点,可以使用connect_by_isleaf:

SQL> select mgr, ename, empno, sal, connect_by_isleaf from emp
  2  start with mgr is null
  3  connect by prior empno = mgr
  4  /

       MGR ENAME           EMPNO        SAL CONNECT_BY_ISLEAF                   
---------- ---------- ---------- ---------- -----------------                   
           KING             7839       5000                 0                   
      7839 JONES            7566       2975                 0                   
      7566 FORD             7902       3000                 0                   
      7902 SMITH            7369        800                 1                   
      7839 BLAKE            7698       2850                 0                   
      7698 ALLEN            7499       1600                 1                   
      7698 WARD             7521       1250                 1                   
      7698 MARTIN           7654       1250                 1                   
      7698 TURNER           7844       1500                 1                   
      7698 JAMES            7900        950                 1                   
      7839 CLARK            7782       2450                 0                   
      7782 MILLER           7934       1300                 1       




SQL> select mgr, ename, sal from emp
  2  where connect_by_isleaf = 1
  3  start with mgr is null
  4  connect by prior empno = mgr
  5  /

       MGR ENAME             SAL                                                
---------- ---------- ----------                                                
      7902 SMITH             800                                                
      7698 ALLEN            1600                                                
      7698 WARD             1250                                                
      7698 MARTIN           1250                                                
      7698 TURNER           1500                                                
      7698 JAMES             950                                                
      7782 MILLER           1300 

如果你想只留下有叶子的分支,你可以使用类似的东西:

SQL> select mgr,ename, sal from (
  2  -- Just branches
  3  select mgr, ename, empno, sal from emp
  4  where connect_by_isleaf = 0
  5  start with mgr is null
  6  connect by prior empno = mgr
  7  )
  8  -- low-level branches
  9  where connect_by_isleaf = 1
 10  start with mgr is null
 11  connect by prior empno = mgr
 12  /

       MGR ENAME             SAL                                                
---------- ---------- ----------                                                
      7566 FORD             3000                                                
      7839 BLAKE            2850                                                
      7839 CLARK            2450