再帰的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はhereです。
更新に確認することがあります:無限再帰の問題 –
「無限再帰」とは何を意味するのでしょうか?階層に理論上の制限はないということですか?または、階層が、ある時点で文字通り、いくつかのブランチ上に子ノードがないようにループすることはありますか? - 編集:後者のように見えるので、ループに達したときに何が起こりたいですか? –
親が子供の場合もあるので、 –