4

さて、この問題を説明するのは少し難しいでしょうが、ここでそれは行きます。

視覚化のようなツリーでレンダリングされるデータを取り込むクエリがあります。このクエリで計算されたylocは、これらの機能にアタッチされた特定のオブジェクトをレンダリングするyの位置を決定するために使用されます。

MAX(coalesce(CAP_TREE2.depth)、0)を使用するだけでは機能しません。そこで、特定の状況でylocが必要なものを示すアルゴリズムを作成しました。

アルゴリズムは次のとおりです。

    if (capability has c2 !=1)
    {
        yloc = 0
    }
    else if (capability is child (at any depth) of capability with c2 != 1)
    {
        yloc = depth - (depth of first parent with c2 != 1)
    }
    else
    {
        y = depth
    }

注: c2はchildNumberを表します(アルファベット順)。したがって、機能に2つの子「A」と「B」がある場合。「A」はc2=1になり、「B」はc2=2になります。

このアルゴリズムをSQL(Oracle 11g R2)に実装しようとすると、多くの問題が発生しました。終了に問題があるのは、アルゴリズムのelseif句ですc2!= 1の機能の子(任意の深さ)であるすべての機能を取得することができました。

ただし、完了できなかった部分は yloc =depth-(c2!= 1の最初の親の深さ)です。

誰かが「c2!= 1の最初の親の深さ」を取得する方法を教えてもらえますか?その値を取得できれば、クエリは最終的に完了します。

これをより明確にするために、サンプルデータに期待する値を示します。

c2!= 1の「投資管理」の最初の親は深さ2の「FPP」です。c2!= 1の「サードパーティ製品管理」の最初の親は深さ2の「FPP」です。「注文管理( PI) "c2!= 1の最初の親は、深さ2の" Operations and Services(PI)"です。

注:申し訳ありませんが、スキーマを変更できません。

これが私がこれまでに持っているものです..一番下のselectステートメントは私が働いているところです。 http://sqlfiddle.com/#!4/55b5a/116

スキーマSQL:

CREATE TABLE capability 
    (
     id int,
     parent_id int,
     name varchar(200)
    )
;

CREATE TABLE tree
  (
     descendantid int,
     ancestorid int,
     depth int
  )
;

INSERT INTO capability (id, parent_id, name) VALUES (1, -1, 'BU-Specific Capabilities');
INSERT INTO capability (id, parent_id, name) VALUES (2, 1, 'PI Capability Model');
INSERT INTO capability (id, parent_id, name) VALUES (3, 2, 'Core Business Processing (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (4, 3, 'Institutional Trust Administration (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (5, 2, 'FPP');
INSERT INTO capability (id, parent_id, name) VALUES (6, 5, 'Investment Management');
INSERT INTO capability (id, parent_id, name) VALUES (7, 6, '3rd party Product Management');
INSERT INTO capability (id, parent_id, name) VALUES (8, 2, 'Operations and Shared Services (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (9, 8, 'Order Management (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (10, 8, 'Settlements (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (11, -1, 'Common Core Capabilities');

INSERT INTO tree (descendantid, ancestorid, depth) VALUES (1, 1, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (2, 1, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (2, 2, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (3, 1, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (3, 2, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (3, 3, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 3, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 4, 0);                                               
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (5, 1, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (5, 2, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (5, 5, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 5, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 6, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 1, 4);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 2, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 5, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 6, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 7, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (8, 1, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (8, 2, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (8, 8, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 8, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 9, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 8, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 10, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (11, 11, 0);

SQLのクエリ:

SELECT
  cap.name,
  max(coalesce(CAP_TREE2.depth,0)) as ydepth,

  CASE
    WHEN cap.parent_id != -1
       THEN DENSE_RANK() OVER (PARTITION BY cap.parent_id ORDER BY cap.name) --child number
    ELSE
       1
  END as c2

FROM capability cap
    INNER JOIN tree CAP_TREE2 ON CAP.id = CAP_TREE2.descendantid

group by cap.name, cap.id, cap.parent_id
;


  WITH ids(id, c2) AS ( -- Find the ids and the ranks
  SELECT
    id, 
    CASE
    WHEN parent_id = -1
      THEN 1
    ELSE
      DENSE_RANK() OVER (PARTITION BY parent_id ORDER BY name) --child number
    END as c2
  FROM capability
),
t(id, depth) AS (
    SELECT id, 0 AS depth FROM ids WHERE c2 != 1  -- Take only ranks not equal to one
UNION ALL
    SELECT c.id, depth+1 FROM capability c JOIN t ON (c.parent_id = t.id)  -- Tree-walking
)
--SELECT DISTINCT cap.name, t.depth
--SELECT DISTINCT cap.name, min(t.depth)
--FROM capability cap JOIN t USING(id)
--group by cap.name


SELECT
  cap.name,
  CASE

    -- cap has childNumber != 1
    WHEN DENSE_RANK() OVER (PARTITION BY cap.parent_id ORDER BY cap.name) != 1
      THEN 0 -- y = 0

    -- cap is child of cap with childNumber != 1
    WHEN cap.name IN (SELECT DISTINCT capa.name
                      FROM capability capa
                      JOIN t USING(id))
         THEN max(coalesce(CAP_TREE2.depth,0)) -- y = depth - (depth of first parent with childNumber != 1)

    ELSE max(coalesce(CAP_TREE2.depth,0)) -- y = depth 

  END as yloc


FROM capability cap
    INNER JOIN tree CAP_TREE2 ON CAP.id = CAP_TREE2.descendantid

group by cap.name,
         cap.id,
         cap.parent_id

また、これが私の希望する結果セットです

NAME                                            DEPTH               C2            YLOC

BU-Specific Capabilities                          0                 1               0       --yloc=depth
Common Core Capabilities                          0                 1               0       --yloc=depth
PI Capability Model                               1                 1               1       --yloc=depth
Core Business Processing (PI)                     2                 1               2       --yloc=depth
FPP                                               2                 2               0       --yloc=0
Operations and Shared Services (PI)               2                 3               0       --yloc=0
Institutional Trust Administration (PI)           3                 1               3       --yloc=depth
Investment Management                             3                 1               1       --yloc=depth - (depth of FPP)
3rd party Product Management                      4                 1               2       --yloc=depth - (depth of FPP)
Order Management (PI)                             3                 1               1       --yloc=depth -(depth of Operations and..)
Settlements (PI)                                  3                 2               0       --yloc=0
4

1 に答える 1

1

親から子への関係をすでに機能テーブルで宣言しているので、ツリーテーブルは必要ないと思います。

oracleからCONNECTBYPRIORコマンドを使用すると、ツリーが構築され、 LEVEL疑似列を使用してノードの深さを判別できます。

唯一注意が必要なのは、深さが1より大きい最初の親ノードを取得することです。私があなたの質問を理解している限り、これはc2である必要があります。結果は列 FIRST_PARENT_IN_DEPTH_G_1にあります。

SELECT ID
    , PARENT_ID
    , NAME
    , DEPTH
    , NODES_PER_LEVEL
    , TO_NUMBER(SUBSTR(ID_PATH, LENGTH(REGEXP_SUBSTR(ID_PATH, '^\s\d{1,}\s')) + 1, 
            INSTR(SUBSTR(ID_PATH, LENGTH(REGEXP_SUBSTR(ID_PATH, '^\s\d{1,}\s')) + 1), ' '))) 
            AS FIRST_PARENT_IN_DEPTH_G_1
FROM (
    SELECT ID
        , PARENT_ID
        , NAME
        , LEVEL DEPTH
        , COUNT(*) OVER (PARTITION BY PARENT_ID, LEVEL) NODES_PER_LEVEL
        , sys_connect_by_path( id, ' ' ) ID_PATH
    FROM capability 
    START WITH PARENT_ID = -1
    CONNECT BY PRIOR ID = PARENT_ID
    )    
ORDER BY ID_PATH
于 2012-11-16T13:41:09.517 に答える