Reputation: 522
I am writing a stored Procedure which should return me result and the same result will be passed as input to the stored Procedure and the recursion should stop after the input and output are same at any particular time.
Below is the stored Procedure/function and the Run Command (New to Stored Procedure).
CREATE FUNCTION dbo.Ancestors (@List VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
WITH CTE AS
(
SELECT DISTINCT Child AS RESULT FROM example WHERE Parent IN( SELECT Id =
Item FROM dbo.SplitInts(@List, ',')) or child IN (SELECT Id = Item FROM
dbo.SplitInts(@List, ','))
UNION ALL
SELECT DISTINCT Parent AS RESULT FROM example WHERE Parent IN( SELECT Id =
Item FROM dbo.SplitInts(@List, ',')) or child IN (SELECT Id = Item FROM
dbo.SplitInts(@List, ','))
)
SELECT RESULT FROM CTE
UNION
SELECT RESULT FROM CTE
GO
CREATE PROCEDURE GetAncestors (@thingID VARCHAR(MAX))
AS
SELECT RESULT FROM dbo.Ancestors(@thingID)
GO
EXEC GetAncestors @thingID = '100'
Result is - '100,101'
EXEC GetAncestors @thingID = '100,101'
Result is - '100,101,102'
EXEC GetAncestors @thingID = '100,101,102'
Result is - '100,101,102'
What i am actually looking for it is to give the result at one shot by passing 100 or 101 or 102
Result should be - '100,101,102'
Below is the Example Table:
| Parent | Child |
|---------------------|------------------|
| 100 | 101 |
|---------------------|------------------|
| 101 | 102 |
|---------------------|------------------|
Upvotes: 4
Views: 17428
Reputation: 32695
It looks like you need a simple recursive query that traverses the tree down starting from a given node. The CTE
returns a list of pairs (Parent, Child)
, so I unioned them together to get a list of individual nodes (and remove duplicates along the way).
Note, that the query is recursive. The CTE (common table expression) references itself.
Sample data
I added few more rows to actually see what is going on.
DECLARE @T TABLE (Parent int, Child int);
INSERT INTO @T VALUES
(100, 101),
(101, 102),
(102, 103),
(103, 104),
(101, 108),
(108, 109),
(208, 209),
(209, 210);
Query
WITH
CTE
AS
(
SELECT
Parent, Child
FROM @T
WHERE Parent = 100
UNION ALL
SELECT
T.Parent, T.Child
FROM
CTE
INNER JOIN @T AS T ON T.Parent = CTE.Child
)
SELECT
Parent AS Result
FROM CTE
UNION
SELECT
Child AS Result
FROM CTE
;
Result
Result
100
101
102
103
104
108
109
You can put the query in the stored procedure like this:
CREATE PROCEDURE GetAncestors(@thingID int)
AS
BEGIN
SET NOCOUNT ON;
WITH
CTE
AS
(
SELECT
Example.Parent, Example.Child
FROM Example
WHERE Parent = @thingID
UNION ALL
SELECT
Example.Parent, Example.Child
FROM
CTE
INNER JOIN Example ON Example.Parent = CTE.Child
)
SELECT
Parent AS Result
FROM CTE
UNION
SELECT
Child AS Result
FROM CTE
;
END
GO
Upvotes: 2