Let's say I have a table with 2 columns ID and ParentID. My data looks like this:
ID ParentID
1 Null
2 1
3 1
4 2
4 2
So to find all relationships based on a given ID my query simplified looks like this:
WITH links ([ID], [ParentID], Depth)
AS
(
--Get the starting link
SELECT
[ID],
[ParentID],
[Depth] = 1
FROM
[MyTable]
WHERE
[ID] = @StartID
UNION ALL
--Recursively get links that are parented to links already in the CTE
SELECT
mt.[ID],
mt.[ParentID],
[Depth] = l.[Depth] + 1
FROM
[MyTable] mt
JOIN
links l ON mt.ParentID = l.ID
WHERE
Depth < 99
)
SELECT
[Depth],
[ID],
[ParentID]
FROM
[links]
Now let's say the data in my table creates a cyclical relationship (4 is parented to 2 and 2 is parented to 4. Forgetting for a moment that there should likely be constraints on the database to prevent this, the above recursive CTE query produce duplicate records (99 of them) because it will recursively evaluate that cyclical relationship between 2 and 4.
ID ParentID
1 Null
2 1
3 1
4 2
2 4
2 4
How can I alter my query to prevent that, assuming that I have no control over preventing the actual data from representing that cyclical relationship. Normally I would put a distinct on the final select but I want the Depth value, which makes every record distinct. I'm also hoping to account for it within the CTE, as a distinct operates on the final select, and is probably not as efficient.