Exiting from recursive common table expression once the result set contains some value
Given the following table:
create table TreeNode
(
ID int not null primary key,
ParentID int null foreign key references TreeNode (ID)
)
How could I write a common table expression to start at the root (WHERE ParentID IS NULL) and traverse its descendants unt开发者_如何学Goil the result set contains some target node (e.g., WHERE ID = n)? It's easy to start at the target node and traverse upward to the root, but that wouldn't generate the same result set. Specifically, nodes having the same parent as the target node wouldn't be included.
My first attempt was:
with Tree as
(
select
ID,
ParentID
from
TreeNode
where
ParentID is null
union all select
a.ID,
a.ParentID
from
TreeNode a
inner join Tree b
on b.ID = a.ParentID
where
not exists (select * from Tree where ID = @TargetID)
)
Which gives the error: Recursive member of a common table expression 'Tree' has multiple recursive references.
NOTE: I'm only interested in top-down traversal.
UPDATE 2:
A third attempt that "traverses" the tree in both directions.
Build a CTE of all ParentIDs
from Target
to root
. Then, select from tree
the nodes
whose ID
or Parent
shows up in the short list.
--
;
WITH Tree
AS ( SELECT ID
,ParentID
FROM TreeNode
WHERE [ID] = @targetId
UNION ALL
SELECT a.ID
,a.ParentID
FROM TreeNode a
INNER JOIN Tree b ON b.ParentID = a.ID
)
SELECT *
FROM [dbo].[TreeNode] n
WHERE EXISTS (SELECT *
FROM [Tree] t
WHERE [t].[ID] = [n].[ID]
OR [t].[ID] = [n].[ParentID]
)
精彩评论