首页 > 解决方案 > Oracle 如何使用“connect by rownum <= n”评估分层查询

问题描述

With A as (

   SELECT 'A' ID FROM DUAL

   UNION ALL 

   SELECT 'B' FROM DUAL

   UNION ALL

   SELECT 'C' FROM DUAL
  )

  SELECT ID 
       , LEVEL AS LVL 
       , ROWNUM 
       , SYS_CONNECT_BY_PATH(LEVEL,'->') AS LV_PATH
       , SYS_CONNECT_BY_PATH(ID,'->') AS ID_PATH
    FROM A
  CONNECT BY ROWNUM <= 3
Result
  ID      LVL   ROWNUM     LV_PATH     ID_PATH
   A       1      1         ->1          ->A
   A       2      2         ->1->2       ->A->A
   A       3      3         ->1->2->3    ->A->A->A
   B       1      4         ->1          ->B
   C       1      5         ->1          ->B

[why B and C has 1 level !?]

在此查询的结果中,B 和 C 只有 1 个值(级别?),但 A 有 3 个值和级别(并且 ID_PATH 结果仅包含 A)

我知道按级别使用连接是建立层次结构,所以我知道它会产生 n + n^n 列

但我不知道为什么按 rownum 连接只显示这些值...

请帮帮我TT

标签: oracle

解决方案


您的分层查询根据条件将层次结构中的一行连接到另一行rownum <= 3

首先,重要的是要了解这rownum是一个伪列,仅当查询决定将生成一行时才会生成它;它总是从1发出的第一条记录开始,并且只会随着每个后续记录的发出而增加(这就是为什么在where rownum > 1执行类似的操作时永远不会得到结果的原因)。

其次,重要的是要了解在 Oracle 中,分层查询是使用深度优先搜索构建的。

您的起始行集是:

1. 'A'
2. 'B'
3. 'C'

查询生成的第一行是:

1. 'A' rownum=1 level=1

查询现在返回并探测原始行集以查找该行的任何直接“子代”。它找到第一条记录'A'。判断这一行是否是我们第一行的子行的条件是rownum <= 3。由于rownum要生成的行是2,所以条件满足;所以发出这一行:

2. 'A' -> 'A' rownum=2 level=2

该查询现在再次探测该行集以查找该行的任何直接“子代”。它找到第一条记录'A'rownum <= 3再次检查条件;因为rownum现在是3,所以条件满足;所以发出这一行:

3. 'A' -> 'A' -> 'A' rownum=3 level=3

该查询现在再次探测该行集以查找该新行的任何直接“子代”。但是,rownum4用于新行,因此无法找到任何“孩子”。

因此它返回到之前生成的第 2 行并继续在行集中搜索任何其他子行;再次,rownum将是4这样它仍然无法找到更多的孩子。它对第 1 行执行相同的操作,并且找不到任何其他子项。

最后,它回到了树的根部,并向前移动到行集中的下一条记录:

4. 'B' rownum=4 level=1

它在那里做同样的事情,在行集中搜索该记录的任何子项,但由于条件而失败。

它最终到达行集中的最后一条记录:

5. 'C' rownum=5 level=1

它也未能找到该记录的任何子项,并且查询已完成。


推荐阅读