Something like this?
;WITH Ordered AS(
SELECTDISTINCT
CASE WHEN l.Col1 <= l.Col2 THEN l.Col1 ELSE l.Col2 END AS Col1,
CASE WHEN l.Col1 <= l.Col2 THEN l.Col2 ELSE l.Col1 END AS Col2
FROM Links l
),
rCTE AS(
SELECT Col1 AS Parent,
Col1,
Col2
FROM Ordered l
UNION ALL
SELECT c.Parent,
l.Col1,
l.Col2
FROM Ordered l
JOIN rCTE c ON l.Col1 = c.Col2
),
Row_Values AS(
SELECT Parent Col1,
Col2,
ROW_NUMBER() OVER( PARTITION BY Col2 ORDER BY Parent) rn
FROM rCTE
)
SELECT Col1, Col2
FROM Row_Values
WHERE rn = 1
ORDER BY Col1, Col2
Unless someone finds a more effective way to do it.