Oracle中递归查询的优化

trnvg8h3  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(159)

我在Oracle中遇到了一个递归查询问题。
假设我有一个带有结构的表“NAMES”:
| 财产|名称|参考|
| --|--|--|
| 0 |迈克| 1 |
| 1 |约翰| 4 |
| 1 |詹姆斯| 4 |
| 1 |罗伯特| 4 |
| 4 |迈克尔| 5 |
| 5 |大卫| 6 |
| 6 |马克|NULL|
简单的递归查询:

WITH rec as
(
 SELECT N_1.PROPERTY, N_1.NAME, N_1.REFERENCE 
 FROM NAMES N_1
 WHERE PROPERTY = 0
 UNION ALL
 SELECT N_2.PROPERTY, N_2.NAME, N_2.REFERENCE  
 FROM NAMES N_2
 JOIN rec r ON T_2.PROPERTY = r.REFERENCE
)
SELECT NAME FROM rec;

女巫给出:
| 名称|
| --|
| 迈克|
| 詹姆斯|
| 约翰|
| 罗伯特|
| 迈克尔|
| 迈克尔|
| 迈克尔|
| 大卫|
| 大卫|
| 大卫|
| 马克|
| 马克|
| 马克|
所以,一切正常。但问题是找到3条记录:詹姆斯,约翰,罗伯特(这是确定的)-然后为他们每个人发现迈克尔(3次,再次确定)-但随后为每个迈克尔的外观发现它自己的大卫(但这是相同的大卫,为相同的迈克尔!)-然后为每个大卫发现它自己的马克(为相同的马克-相同的大卫)。
我的目标是找到从Mike开始的完整层次结构,即。通过REFERENCE = PROPERTY查找从Mike步行可以到达的所有元素。所以,我的理想结果集看起来像:
| 名称|
| --|
| 迈克|
| 詹姆斯|
| 约翰|
| 罗伯特|
| 迈克尔|
| 大卫|
| 马克|
我知道我可以通过添加“区别”来达到我的目标:

...
SELECT DISTINCT NAME FROM rec;

但问题是,额外的记录(过多的大卫和马克)将发现无论如何-但将只是从结果中丢弃。这对我来说是不好的,因为我的真实的表比示例复杂得多,额外的搜索需要大量的时间。所以,有没有办法对数据库说- '如果你找到迈克尔3次-不要搜索他的参考3次-搜索一次'。
提前感谢:)
P.S.首先,我想做的是:

WITH rec as
(
...
 UNION ALL
 SELECT DISTINCT N_2.PROPERTY, N_2.NAME, N_2.REFERENCE  
 FROM NAMES N_2
 JOIN rec r ON T_2.PROPERTY = r.REFERENCE
)
SELECT NAME FROM rec;

但Oracle不喜欢它。

wmvff8tz

wmvff8tz1#

一种方法可能是找到propertyreferenceDISTINCT对,然后生成层次结构,并将JOIN返回到NAMES表以获得名称:

WITH relationships (property, reference) AS (
  SELECT DISTINCT property, reference
  FROM   names
),
hierarchy (property) AS (
  SELECT property
  FROM   relationships
  START WITH property = 0
  CONNECT BY PRIOR reference = property
)
SELECT n.name
FROM   hierarchy h
       INNER JOIN names n
       ON (h.property = n.property)

WITH relationships (property, reference) AS (
  SELECT DISTINCT property, reference
  FROM   names
),
hierarchy (property, reference) AS (
  SELECT property, reference
  FROM   relationships
  WHERE  property = 0
UNION ALL
  SELECT r.property, r.reference
  FROM   hierarchy h
         INNER JOIN relationships r
         ON h.reference = r.property
)
SELECT n.name
FROM   hierarchy h
       INNER JOIN names n
       ON (h.property = n.property)

哪个输出:
| 名称|
| --|
| 迈克|
| 约翰|
| 詹姆斯|
| 罗伯特|
| 迈克尔|
| 大卫|
| 马克|
fiddle

相关问题