简体   繁体   English

分层查询最多3次自联接表

[英]Hierarchical Query to Self-Join Table Max 3 Times

I have an Oracle DB with a table with the following columns: 我有一个带有以下各列的表的Oracle DB:

    ID | PARENTID | DETAIL1
    ------------------------
    1  | NULL     | BLAH1
    2  | 1        | BLAH2
    3  | 2        | BLAH3
    4  | 2        | BLAH4
    5  | NULL     | BLAH5
    6  | 5        | BLAH6
    7  | 6        | BLAH7
    8  | 5        | BLAH8
    9  | 5        | BLAH9
    10 | 8        | BLAH10

I prepared a self-join for 我准备了一个自我加入

    SELECT    PARENT.ID AS "PID",
              PARENT.DETAIL1 AS "PDETAIL1",
              CHILD.ID AS "CID",
              CHILD.DETAIL1 AS "CDETAIL1" 

      FROM    table1 CHILD

      LEFT OUTER JOIN table1 PARENT

      ON      PARENT.ID = CHILD.PARENTID
      WHERE   PARENTID IS NOT NULL;

The output looks as shown below: 输出如下所示:

    PID | PDETAIL1 | CID | CDETAIL1|
    --------------------------------
    1   | BLAH1    | 2   | BLAH2   |
    2   | BLAH2    | 3   | BLAH3   |
    2   | BLAH2    | 4   | BLAH4   |
    5   | BLAH5    | 6   | BLAH6   |
    6   | BLAH6    | 7   | BLAH7   |
    5   | BLAH5    | 8   | BLAH8   |
    5   | BLAH5    | 9   | BLAH9   |
    8   | BLAH8    | 10  | BLAH10  |

Pretty straight forward. 非常简单。 I would like to know if this self join can be done as a hierarchical/recursive query. 我想知道是否可以将这种自我联接作为层次/递归查询来完成。 The maximum nesting depth is 3. The target output should look like this: 最大嵌套深度为3。目标输出应如下所示:

    GPID | GPDETAIL1 | PID | PDETAIL1 | CID  | CDETAIL1 |
    ---------------------------------------------------
    1    | BLAH1     | 2   | BLAH2    | 3    | BLAH3    |
    1    | BLAH1     | 2   | BLAH2    | 4    | BLAH4    |
    5    | BLAH5     | 6   | BLAH6    | 7    | BLAH7    |
    5    | BLAH5     | 8   | BLAH8    | 10   | BLAH10   |
    5    | BLAH5     | 9   | BLAH9    | NULL | NULL     |

Google isn't helping me, there is a ton of information related to hierarchical queries, but nothing including self-joins AND hierarchical queries and most questions appear to be similar (on the surface), but nothing guiding me to what I need. Google并没有帮助我,有大量与分层查询有关的信息,但是没有任何信息(包括自我联接和分层查询),而且大多数问题在表面上看起来都是相似的,但是没有什么可以指导我满足我的需求。 I'm a SQL newbie so unless the answer is specific, I could be missing it. 我是SQL新手,因此,除非答案是特定的,否则我可能会错过它。

You just need to join to the table one more time to get the children. 您只需要再join一次餐桌就可以得到孩子们。 So basically have a grandparent alias, parent alias and child alias and join accordingly: 因此,基本上有一个祖父母别名,父别名和子别名,并相应地join

select 
    gp.id as gpid,
    gp.detail as gpdetail1,
    p.id as pid,
    p.detail as pdetail1,
    c.id as cid,
    c.detail as cdetail1
from yourtable gp
    left join yourtable p on gp.id = p.parentid
    left join yourtable c on p.id = c.parentid
where gp.parentid is null

there is a ton of information related to hierarchical queries, but nothing including self-joins AND hierarchical queries 有大量与分层查询有关的信息,但没有任何信息包括自我联接和分层查询

You don't need both, the hierarchical query is the self-join. 您不需要两者,层次查询自连接。

You can get close starting with a hierarchical query like: 您可以从类似于以下的分层查询开始:

select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
  prior id as pid, prior detail1 as pdetail1,
  id as cid, detail1 as cdetail1,
  level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid

See the docs for what connect_by_root and connect_by_isleaf mean. 请参阅文档 ,了解connect_by_root和connect_by_isleaf的含义。 You're interested in the leaf nodes, but this: 您对叶节点感兴趣,但是:

select *
from (
  select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
    prior id as pid, prior detail1 as pdetail1,
    id as cid, detail1 as cdetail1,
    level as lvl, connect_by_isleaf as is_leaf
  from table1
  start with parentid is null
  connect by prior id = parentid
)
where is_leaf = 1;

... doesn't get quite what you want: ...没有得到您想要的东西:

      GPID GPDETA        PID PDETAI        CID CDETAI        LVL    IS_LEAF
---------- ------ ---------- ------ ---------- ------ ---------- ----------
         1 BLAH1           2 BLAH2           3 BLAH3           3          1
         1 BLAH1           2 BLAH2           4 BLAH4           3          1
         5 BLAH5           6 BLAH6           7 BLAH7           3          1
         5 BLAH5           8 BLAH8          10 BLAH10          3          1
         5 BLAH5           5 BLAH5           9 BLAH9           2          1

From your sample output you don't want 5/BLAH5 in the parent columns of the last row as they are the grandparents; 从示例输出中,您不希望在最后一行的父列中使用5 / BLAH5,因为它们是祖父母。 you want the child values promoted to parent status. 您希望将子级值提升为父级状态。 You can manipulate the parent and child values a little though: 不过,您可以稍微操纵父级和子级值:

select gpid, gpdetail1,
  case lvl when 2 then cid else pid end as pid,
  case lvl when 2 then cdetail1 else pdetail1 end as pdetail1,
  case lvl when 2 then null else cid end as cid,
  case lvl when 2 then null else cdetail1 end as cdetail1
from (
  select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
    prior id as pid, prior detail1 as pdetail1,
    id as cid, detail1 as cdetail1,
    level as lvl, connect_by_isleaf as is_leaf
  from table1
  start with parentid is null
  connect by prior id = parentid
)
where is_leaf = 1;

      GPID GPDETA        PID PDETAI        CID CDETAI
---------- ------ ---------- ------ ---------- ------
         1 BLAH1           2 BLAH2           3 BLAH3 
         1 BLAH1           2 BLAH2           4 BLAH4 
         5 BLAH5           6 BLAH6           7 BLAH7 
         5 BLAH5           8 BLAH8          10 BLAH10
         5 BLAH5           9 BLAH9                   

But with only three fixed levels just joining again is simpler easier to understand... 但是只有三个固定级别,再次加入更加容易理解...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM