我在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不喜欢它。
1条答案
按热度按时间wmvff8tz1#
一种方法可能是找到
property
和reference
的DISTINCT
对,然后生成层次结构,并将JOIN
返回到NAMES
表以获得名称:或
哪个输出:
| 名称|
| --|
| 迈克|
| 约翰|
| 詹姆斯|
| 罗伯特|
| 迈克尔|
| 大卫|
| 马克|
fiddle