0

興味深い問題があります。少なくともそう思います。したがって、上記の構造を持つテーブル (codes_table) があります (これはツリー メニューです)。ツリーは、2 つの整数と (常に) 次のようなドット パターンによって定義されます。

COD_MENU               NAME
01.                 Biggest Node
01.01.              Sun of 01.
01.01.01.           Sun of 01.01.
01.01.01.01.        Sun of 01.01.01.
01.01.01.02.        Sun of 01.01.01.
01.01.01.03.        Sun of 01.01.01.
01.01.01.04.        Sun of 01.01.01.
01.01.01.05.        Sun of 01.01.01.
01.02.              Sun of 01.
01.03.              Sun of 01.
01.03.01.           Sun of 01.03.
(etc...)

私が必要とするのは、次のような新しい構造の名前として実際の COD_MENU を入れて、その父へのキーをフォアイングする数値 ID を持つ構造を持つ新しいテーブルに挿入スクリプトを生成することです。

ID     FATHER_ID         NAME 
1        NULL            01.
2        1               01.01.
3        2               01.01.01.
4        3               01.01.01.01.
5        3               01.01.01.02.
6        3               01.01.01.03.
7        3               01.01.01.04.
8        3               01.01.01.05.
9        1               01.02.
10       1               01.03.
11       10              01.03.01.

これは、再帰的な手順を使用して plsql ブロッ​​ク コードで既に実行しています。上記は参照用の私の実際のコードです。

declare
   auxId integer;

   procedure findNodes( pCod varchar2, pCurrId in out integer, pFatherId in integer  ) is
        ctHasSuns integer; 
        father    varchar2(20);
        idFhtTmp     integer;
     begin

        idFhtTmp  := pFatherId;

        if idFhtTmp is null then
            father := 'null';
        else
            father := idFhtTmp;
        end if;
        ctHasSuns := 0;

        SELECT count(cod_menu) into ctHasSuns FROM codes_table where SUBSTR (cod_menu, 1,LENGTH (cod_menu) - 3) = pCod and rownum < 10;

        if (ctHasSuns > 0 or pCurrId = 1) then
            dbms_output.put_line ('insert into newtable ( id, idfather, menu ) values ( '||pCurrId||','||father||', '''||pCod||''' );');
            idFhtTmp := pCurrId;
            for cHasSuns in ( SELECT cod_menu FROM codes_table where SUBSTR (cod_menu, 1,LENGTH (cod_menu) - 3) = pCod and rownum < 10 order by cod_menu) loop
                pCurrId := pCurrId + 1;
                findNodes( cHasSuns.cod_menu, pCurrId, idFhtTmp );
            end loop;
        else
            dbms_output.put_line ('insert into newtable ( id, idfather, menu ) values ( '||pCurrId||','||father||', '''||pCod||''' );');
        end if;

     end;

begin
  auxId := 1;
  findNodes( '01.', auxId, null );
end;

私がやろうとしているのは、CONNECT BY / START WITH / ROWNUM および LEVEL ステートメントを使用して単一のクエリでそれを達成し、必要に応じて同じテーブルとの結合を使用することです。いろいろ試しましたが、解決策が思いつきませんでした。これは単なる好奇心です。

私ができる最も近いことは上記の選択ですが、太陽ではなく父親のIDを持っているだけです

WITH q AS (
select rownum id, father  from (
select a.noh father, count(*) 
from (select cod_menu noh, substr( cod_menu, 1, length(cod_menu)-3) as nofather from codes_table) a,
     (select cod_menu noh, substr( cod_menu, 1, length(cod_menu)-3) as nofather from codes_table) b
where a.noh = b.nofather
group by a.noh
having count(*) > 0 
order by a.noh)
), 
b as (
 SELECT cod_menu filho, father
  FROM (select cod_menu, substr( cod_menu, 1, length(cod_menu)-3) as father from codes_table)
  START WITH father is null
CONNECT BY prior cod_menu = father 
  ORDER BY cod_menu
)
SELECT * FROM q, b where q.father = b.father;

お時間をいただき、ありがとうございました。

4

1 に答える 1

1

以下の解決策を試してください:

CREATE TABLE codes_table (
  cod_menu VARCHAR2(40),
  name VARCHAR2(40)
);

INSERT INTO codes_table VALUES ('01.', 'Biggest Node');
INSERT INTO codes_table VALUES ('01.01.', 'Sun of 01.');
INSERT INTO codes_table VALUES ('01.01.01.', 'Sun of 01.01.');
INSERT INTO codes_table VALUES ('01.01.01.01.', 'Sun of 01.01.01.');
INSERT INTO codes_table VALUES ('01.01.01.02.', 'Sun of 01.01.01.');
INSERT INTO codes_table VALUES ('01.01.01.03.', 'Sun of 01.01.01.');
INSERT INTO codes_table VALUES ('01.01.01.04.', 'Sun of 01.01.01.');
INSERT INTO codes_table VALUES ('01.01.01.05.', 'Sun of 01.01.01.');
INSERT INTO codes_table VALUES ('01.02.', 'Sun of 01.');
INSERT INTO codes_table VALUES ('01.03.', 'Sun of 01.');
INSERT INTO codes_table VALUES ('01.03.01.', 'Sun of 01.03.');

COMMIT;

SELECT
    id,
    PRIOR id AS father_id,
    cod_menu AS name
  FROM (
    SELECT
      cod_menu,
      name,
      row_number() OVER (ORDER BY cod_menu) AS id
    FROM
      codes_table
)
START WITH cod_menu = '01.'
CONNECT BY SUBSTR(cod_menu, 1, LENGTH(cod_menu) - 3) = PRIOR cod_menu
;

SQLFiddleで確認してください:それをいじってください

于 2013-10-17T20:48:06.003 に答える