我有一個父子關系表,對于一個節點串列(我們稱它們為“根”),我想看看哪些節點有一個(或多個)具有某些特征的父(我們稱其為“壞”)。
我可以撰寫一個遞回 CTE 來查找所有父節點,然后將它們與壞節點串列進行比較。但是,這很慢,因為一個節點可以有很多父節點,而我對找到所有父節點并不感興趣。我只需要知道某些父母是否不好。當找到一個壞的父母時,我想停止對特定根的遞回。

這是查詢的樣子:
with recursive_table (root, level, path, current_node) as (
select root = node, level = 0, path = 'root', current_node = node
from seed_nodes
UNION ALL
select o.root, level 1, CONCAT(e.parent, '/', o.path), e.parent
from structure e
inner join recursive_table o
on o.current_node = e.child
-- it is possible to stop searching this particular branch if we pass a bad node
and o.node not in (
select b.node
from bad_node_list b
)
-- it is NOT possible to stop investigating a particular root if any bad node is found
and o.root not in (
select oo.root
from recursive_table oo
join bad_node_list b
on oo.current_node = b.node
where o.root = oo.root
)
)
select *
from seed_nodes a
outer apply (
select top 1 current_node
from recursive_table b
join bad_node_list c
on b.current_node = c.node
where a.node = b.root
) b
正如注釋中的代碼所說,當找到壞節點時,可以停止在分支中搜索。但是當找到第一個壞節點時,不可能完全停止搜索根。SQL Server 將給出錯誤“公用表運算式‘recursive_table’的遞回成員具有多個遞回參考。”
有沒有辦法解決?(我知道 SQL Server 試圖禁止一些其他函式,例如聚合函式,但有可能繞過它并仍然使用它們。)
uj5u.com熱心網友回復:
有沒有辦法在遞回函式中訪問其他分支?不。
SQL Server 中的遞回已實作,因此這是不可能的。此外,遞回實際上是深度優先的,而不是廣度優先的(您可能相信 SQL 遞回的語法)。
可以通過使用回圈將其重寫為實際的廣度優先搜索,并包含在找到第一個壞節點時停止搜索的條件。
對于我的特定資料集,這并沒有提高性能,而是增加了大約 50% 的時間(15 分鐘而不是 10 分鐘)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/528346.html
上一篇:這是尾遞回嗎?為什么?
