oracle - 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
解决方案
您的分层查询根据条件将层次结构中的一行连接到另一行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
该查询现在再次探测该行集以查找该新行的任何直接“子代”。但是,rownum
将4
用于新行,因此无法找到任何“孩子”。
因此它返回到之前生成的第 2 行并继续在行集中搜索任何其他子行;再次,rownum
将是4
这样它仍然无法找到更多的孩子。它对第 1 行执行相同的操作,并且找不到任何其他子项。
最后,它回到了树的根部,并向前移动到行集中的下一条记录:
4. 'B' rownum=4 level=1
它在那里做同样的事情,在行集中搜索该记录的任何子项,但由于条件而失败。
它最终到达行集中的最后一条记录:
5. 'C' rownum=5 level=1
它也未能找到该记录的任何子项,并且查询已完成。
推荐阅读
- bluetooth-lowenergy - iBeacon 名称未显示在 ESP32 BLE 扫描仪中
- swift - 将 ARFaceGeometry 保存到 OBJ 文件
- vue.js - 找不到Vue js路由404和资产
- laravel - Laravel 说在表单中给出动作时缺少必需的参数
- r - 如何以一定次数重复堆叠同一行
- google-apps-script - 如何在谷歌电子表格中 B 列的每个填充单元格中获取文本
- nginx - Apache Zeppelin websockets 是否经过身份验证?
- python - Tensorflow 的 name_scope 在 Tensorboard 中不起作用
- python-3.x - AttributeError:模块'pygame.event'没有属性'type'
- python - 如何在函数内打印变量