【问题标题】:How to build a hierarchy in Oracle SQL as efficiently as possible如何在 Oracle SQL 中尽可能高效地构建层次结构
【发布时间】:2020-12-19 22:01:48
【问题描述】:

这是在 Oracle SQL 中使用他们的 BI Publisher 数据模型工具

假设你有两张桌子:

hierarchy_table acct_description_table

在这两个表中你有这些列:

hierarchy_table
+------------+-----------+-------+
| primarykey | parentkey | depth |
+------------+-----------+-------+

acct_description_table
+------------+-------------+
| acct_value | description |
+------------+-------------+

你想用这些数据建立一个像这样的层次结构(省略描述):

+----------------+----------------+----------------+
|  acct_depth_0  |  acct_depth_1  |  acct_depth_2  | . . .
+----------------+----------------+----------------+
|     450000     |     450040     |                | . . .
+----------------+----------------+----------------+
|     450000     |     450050     |     450051     | . . .
+----------------+----------------+----------------+

实现这一目标的最佳方法是什么?到目前为止,我有以下 SQL:

select distinct
  t1.acct,
  t1.desc,
  t2.acct,
  t2.desc,
  t3.acct,
  t3.desc,
  t4.acct,
  t4.desc,
  t5.acct,
  t5.desc,
  t6.acct,
  t6.desc
from (select tree.primarykey acct, act.description desc 
      from hierarchy_table tree, acct_description_table act 
      where 1=1
        and tree.depth = 0
        and act.acct_value = tree.primarykey
     ) t1
left join (select tree.primarykey acct, tree.parentkey parent, act.description desc 
           from hierarchy_table tree, acct_description_table act 
           where 1=1
             and tree.depth = 1
             and act.acct_value = tree.primarykey
     ) t2
  on 1=1 and t1.acct = t2.parent
...
...
...
left join (select tree.primarykey acct, tree.parentkey parent, act.description desc 
           from hierarchy_table tree, acct_description_table act 
           where 1=1
             and tree.depth = 5
             and act.acct_value = tree.primarykey
     ) t6
  on 1=1 and t5.acct = t6.parent

正如您在这样的查询中看到的,我们将执行 5 次不同的 left join 操作来完成表格。我研究了递归以帮助加快此查询。但是,我不确定如何对其进行编码以满足我们对每个深度对应的列的需求。

有没有人做过类似的事情?或者有谁知道我们可以比由 5 个不同的左连接组成的当前查询更快地做到这一点?谢谢!

【问题讨论】:

    标签: sql oracle recursion oracle-sqldeveloper hierarchy


    【解决方案1】:

    Oracle 的CONNECT BY 功能适用于层次结构并且非常高效。以下是您可以将其用于数据的一种方式:

    with hierarchy_table ( primarykey, parentkey, depth ) as 
    -- This is test data, you would not have this WITH clause...
    ( SELECT '450000', null, 0 FROM DUAL UNION ALL
      SELECT '450040', '450000', 1 FROM DUAL UNION ALL
      SELECT '450050', '450000', 1 FROM DUAL UNION ALL  
      SELECT '450051', '450050', 2 FROM DUAL ),
        acct_description_table ( acct_value, description ) AS
    -- This is test data, you would not have this WITH clause...
    ( SELECT '450000', 'Acct #450000' FROM DUAL UNION ALL
      SELECT '450040', 'Acct #450040' FROM DUAL UNION ALL
      SELECT '450050', 'Acct #450050' FROM DUAL UNION ALL  
      SELECT '450051', 'Acct #450051' FROM DUAL )
    -- Real query starts here
    SELECT REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(ht.primarykey,':'),'[^:]+',1,1) acct1,
           REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(ht.primarykey,':'),'[^:]+',1,2) acct2,
           REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(ht.primarykey,':'),'[^:]+',1,3) acct3,
           REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(ht.primarykey,':'),'[^:]+',1,4) acct4,
           REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(ht.primarykey,':'),'[^:]+',1,5) acct5,
           REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(ht.primarykey,':'),'[^:]+',1,6) acct6,
           adt.description
    FROM    hierarchy_table ht
    INNER JOIN acct_description_table adt ON adt.acct_value = ht.primarykey
    WHERE CONNECT_BY_ISLEAF = 1
    START WITH ht.parentkey IS NULL
    CONNECT BY ht.parentkey = PRIOR ht.primarykey
    AND ht.depth = PRIOR ht.depth + 1  -- There is actually no need for the "DEPTH" column in your table.
    AND LEVEL <= 6;
    
    +--------+--------+--------+-------+-------+-------+--------------+
    | ACCT1  | ACCT2  | ACCT3  | ACCT4 | ACCT5 | ACCT6 | DESCRIPTION  |
    +--------+--------+--------+-------+-------+-------+--------------+
    | 450000 | 450040 |        |       |       |       | Acct #450040 |
    | 450000 | 450050 | 450051 |       |       |       | Acct #450051 |
    +--------+--------+--------+-------+-------+-------+--------------+
    

    【讨论】:

    • 哇,这是一个很好的答案!我实现了这一点,它很快地拉动了层次结构。您的查询是 20 行(我做了一些更改),而我们之前的查询是 80 多行。非常好!
    猜你喜欢
    • 2012-12-09
    • 2023-03-21
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 2011-09-19
    • 2013-12-11
    相关资源
    最近更新 更多