sql >> データベース >  >> RDS >> Oracle

connectby句を使用した再帰的挿入

    すべてのリーフノードが同じ高さ(ここではlvl =4)にある場合、ROLLUPを使用して単純なCONNECTBYクエリを記述できます。

    SQL> SELECT lvl0,
      2         regexp_substr(path, '[^/]+', 1, 2) lvl1,
      3         regexp_substr(path, '[^/]+', 1, 3) lvl2,
      4         SUM(VALUE) sum_value
      5    FROM (SELECT sys_connect_by_path(t.element, '/') path,
      6                 connect_by_root(t.element) lvl0,
      7                 t.element, d.VALUE, LEVEL lvl
      8             FROM tree t
      9             LEFT JOIN DATA d ON d.element = t.element
     10            START WITH t.PARENT IS NULL
     11           CONNECT BY t.PARENT = PRIOR t.element)
     12   WHERE VALUE IS NOT NULL
     13     AND lvl = 4
     14   GROUP BY lvl0, ROLLUP(regexp_substr(path, '[^/]+', 1, 2),
     15                         regexp_substr(path, '[^/]+', 1, 3));
    
    LVL0 LVL1  LVL2   SUM_VALUE
    ---- ----- ----- ----------
    P0   P1    P11            6
    P0   P1    P12            6
    P0   P1                  12
    P0   P2    P21            6
    P0   P2    P22            6
    P0   P2                  12
    P0                       24
    

    挿入は次のようになります:

    INSERT INTO data (element, value) 
    (SELECT coalesce(lvl2, lvl1, lvl0), sum_value
       FROM <query> d_out
      WHERE NOT EXISTS (SELECT NULL
                          FROM data d_in
                         WHERE d_in.element = coalesce(lvl2, lvl1, lvl0)));
    

    葉のノードの高さが不明/無制限の場合、これはより毛深いものになります。 ROLLUPは考慮される列の数を正確に知る必要があるため、上記のアプローチは機能しません。

    その場合、自己結合でツリー構造を使用できます:

    SQL> WITH HIERARCHY AS (
      2     SELECT t.element, path, VALUE
      3       FROM (SELECT sys_connect_by_path(t.element, '/') path,
      4                    connect_by_isleaf is_leaf, ELEMENT
      5                FROM tree t
      6               START WITH t.PARENT IS NULL
      7              CONNECT BY t.PARENT = PRIOR t.element) t
      8       LEFT JOIN DATA d ON d.element = t.element
      9                       AND t.is_leaf = 1
     10  )
     11  SELECT h.element, SUM(elements.value)
     12    FROM HIERARCHY h
     13    JOIN HIERARCHY elements ON elements.path LIKE h.path||'/%'
     14   WHERE h.VALUE IS NULL
     15   GROUP BY h.element
     16   ORDER BY 1;
    
    ELEMENT SUM(ELEMENTS.VALUE)
    ------- -------------------
    P0                       24
    P1                       12
    P11                       6
    P12                       6
    P2                       12
    P21                       6
    P22                       6
    


    1. Oracle10とJDBC:比較時にCHARに末尾のスペースを無視させる方法は?

    2. SQL Serverのストアドプロシージャまたはユーザー定義関数のパラメーターを返す(T-SQLの例)

    3. MySQLでの行から列への変換

    4. SQLiteのCount()結果から重複を削除