【问题标题】:hierarchical query, accounts tree分层查询,账户树
【发布时间】:2016-01-04 09:23:11
【问题描述】:

我在搜索父或子帐户时遇到了分层查询,通常让我们假设一个示例:

表帐户:

Account    Parent
217518     217518 or null
304229     217518
424590     217518
378327     217518
491504     378327
234123     491504

所以层次结构看起来:

现在,我得到了表格“SHOW_PARENT_CHILD_ACC”,我将在其中插入我想显示的帐户。 (我需要在分层查询中使用它)

插入 Show_parent_child_acc(acc) 值 (304229)。

查询应返回所有帐户 ID,因此:

304229     
424590     
378327 
217518    
491504     
234123     

我会的时候也一样 插入 show_parent_cild_acc(acc) 值 (234123)

查询应返回所有帐户 ID,因此:

304229     
424590     
378327 
217518    
491504     
234123  

换句话说,无论我将哪个帐户(父母/孩子或孩子的孩子)插入到 show_parent_child_acc 表中。查询应该返回整个帐户层次结构

现在我有类似的东西:

WITH acc_to_delete( ID ) AS (
                            select case when parentaccount is null then accountid else parentaccount end from account where accountid in                                          
                                 (select acc from show_parent_child_acc) 
                          )
                          SELECT accountid id_acc,case when parentaccount is null then accountid else parentaccount end parentaccount
                          FROM   account p
                          START WITH
                           EXISTS( SELECT 'X'
                                    FROM   acc_to_delete w
                                    WHERE  p.accountid = w.ID
                                    )
                          CONNECT BY accountid = PRIOR parentaccount
                          union
                          SELECT accountid id_acc,case when parentaccount is null then accountid else parentaccount end parentaccount
                          FROM   account p
                          START WITH
                          EXISTS( SELECT 'X'
                                    FROM   acc_to_delete w
                                    WHERE  p.accountid = w.ID
                                    )
                          CONNECT BY PRIOR accountid = parentaccount 
                      

但它没有按预期工作(它在我放入 SHOW_PARENT_CHILD_ACC 的地方工作正常:217518..)

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    我将从查找根 id(子查询“root”)开始,然后创建典型的层次结构:

    with 
      tmp as (select acc from show_parent_child_acc ),
      root as (
        select max(acnt) keep (dense_rank last order by lvl) root
          from (
            select nvl(parentaccount, accountid) acnt, level lvl  
              from account a cross join tmp
              connect by nocycle prior parentaccount = accountid
              start with accountid = acc or parentaccount = acc ))
    select accountid from account cross join root
      connect by nocycle prior accountid = parentaccount
      start with parentaccount = root.root
    union select root from root
    

    测试数据和输出:

    create table account (accountid number(8), parentaccount number(8));
    insert into account values (217518, 217518);
    insert into account values (304229, 217518);
    insert into account values (424590, 217518);
    insert into account values (378327, 217518);
    insert into account values (491504, 378327);
    insert into account values (234123, 491504);
    create table show_parent_child_acc (acc number(8));
    insert into show_parent_child_acc values (234123);
    
    AccountID
    ---------
       217518
       234123
       304229
       378327
       424590
       491504
    

    【讨论】:

    • 很高兴我能帮上忙。这里的问题是根值没有明确定义。在您的示例中,217518 根本不存在 具有与 id 相同的父级 具有空父级。我尝试编写处理所有情况的查询,这就是出现nocycle 的原因。 我 zawsze to fajnie pomóc rodakowi, pozdrawiam ;-)
    【解决方案2】:

    进一步修改原始查询如下。

    WITH acc_to_delete( ID ) AS (
                            select case when parentaccount is null then accountid else parentaccount end from account where accountid in                                          
                                 (select acc from show_parent_child_acc) 
                          )                      
    SELECT DISTINCT accountid id_acc, case when parentaccount is null then accountid else parentaccount end parentaccount 
    FROM account START WITH parentaccount in
    (                          
        SELECT case when parentaccount is null then accountid else parentaccount end parentaccount
        FROM   account p 
        START WITH
        EXISTS( SELECT 'X'
                FROM   acc_to_delete w
                WHERE  p.accountid = w.ID
            )
        CONNECT BY nocycle accountid = PRIOR parentaccount 
        UNION
        SELECT case when parentaccount is null then accountid else parentaccount end parentaccount
        FROM   account p 
        START WITH
        EXISTS( SELECT 'X'
                FROM   acc_to_delete w
                WHERE  p.accountid = w.ID
                )
        CONNECT BY nocycle PRIOR accountid =  parentaccount
    ) 
    CONNECT BY NOCYCLE parentaccount = PRIOR accountid
    

    主要是收集所有对应的父母,然后得到他们的孩子。

    【讨论】:

      猜你喜欢
      • 2011-08-13
      • 1970-01-01
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      相关资源
      最近更新 更多