使用递归 CTE 进行图行走的痛苦问题。这是在图中找到连通子图的问题。使用递归 CTE 的挑战是防止不必要的递归 - 即 SQL Server 中的无限循环,这通常意味着将它们存储在字符串中。
这个想法是获取所有连接的节点对的列表(并且节点与其自身连接)。然后,从连接节点列表中取最小值,并将其用作连接子图的 id。
另一个想法是从一个节点在两个方向上遍历图形。这确保访问所有可能的节点。以下是完成此操作的查询:
with fullt as (
select keyA, keyB
from t
union
select keyB, keyA
from t
),
CTE as (
select t.keyA, t.keyB, t.keyB as last, 1 as level,
','+cast(keyA as varchar(max))+','+cast(keyB as varchar(max))+',' as path
from fullt t
union all
select cte.keyA, cte.keyB,
(case when t.keyA = cte.last then t.keyB else t.keyA
end) as last,
1 + level,
cte.path+t.keyB+','
from fullt t join
CTE
on t.keyA = CTE.last or
t.keyB = cte.keyA
where cte.path not like '%,'+t.keyB+',%'
) -- select * from cte where 'g' in (keyA, keyB)
select t.keyA, t.keyB,
dense_rank() over (order by min(cte.Last)) as grp,
min(cte.Last)
from t join
CTE
on (t.keyA = CTE.keyA and t.keyB = cte.keyB) or
(t.keyA = CTE.keyB and t.keyB = cte.keyA)
where cte.path like '%,'+t.keyA+',%' or
cte.path like '%,'+t.keyB+',%'
group by t.id, t.keyA, t.keyB
order by t.id;
SQLFiddle 在这里。