再帰的 CTE を使用したグラフ ウォーキングの痛ましい問題。これは、グラフ内で接続されたサブグラフを見つける問題です。再帰 CTE を使用する際の課題は、不当な再帰、つまり無限ループを防ぐことです。SQL Server では、これは通常、それらを文字列に格納することを意味します。
アイデアは、接続されている (そしてノードがそれ自体に接続されている) ノードのすべてのペアのリストを取得することです。次に、接続されたノードのリストから最小値を取得し、これを接続されたサブグラフの ID として使用します。
もう 1 つのアイデアは、ノードから両方向にグラフをたどることです。これにより、すべての可能なノードが訪問されることが保証されます。以下は、これを実現するクエリです。
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 はこちらです。