「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > 再帰CTEを使用して、すべての接続されたサブグラフを無向グラフで見つけるためのヒント

再帰CTEを使用して、すべての接続されたサブグラフを無向グラフで見つけるためのヒント

2025-04-14に投稿されました
ブラウズ:488

How to Find All Connected Subgraphs in an Undirected Graph Using a Recursive CTE?

対応のないグラフのすべての接続されたサブグラフを見つける方法その他表:

id

識別子2

a c f 3 7 9 識別子
&] 1
2 b
&] g
4 c h
] 6 d f
7
l h
が望むoutput:
gr_id gr.members
a 1 (a、c、g、h、l)
b

2

(b 、d、f、j)(b、d、f、j) e 2 (b、d、f、j)(a、c、g、h、l) h 1 (a、c、g、h、l) j 2 (b、d、f、j) k 3 (e、k) l 1 (a、c、g、g、h、l) &&] the次のクエリでは、単一の再帰クエリを使用して、接続されたすべてのサブグラフを見つけます: cte_idents として ( 識別として識別1を選択します @tから 連合 識別として識別2を選択します @tから )) 、cte_pairs として ( 識別1、識別2を選択します @tから 識別1識別2 連合 識別2を識別1、識別1として識別2として選択します @tから 識別1識別2 )) 、cte_recursive として ( 選択します cast(cte_idents.ident as varchar(8000)) 、識別1 、識別2 、cast( '、'識別1 '、'識別2 '、' as varchar(8000))として識別 、1 lvlとして から cte_pairs cte_idents.ident = cte_pairs.ident1にcte_identsを結合します ユニオンすべて 選択します cte_recursive.anchorident 、cte_pairs.ident1 、cte_pairs.ident2 、cast(cte_recursive.identpath cte_pairs.ident2 '、' as varchar(8000))as identpath 、cte_recursive.lvl 1 as lvl から cte_pairs cte_recursive.ident2 = cte_pairs.ident1の内側結合CTE_RECURSIVE どこ cte_recursive.identpathはcastのようではありません( '%、' cte_pairs.ident2 '、%' as varchar(8000)) )) 、cte_recursionresult として ( Anchorident、Ident1、Ident2を選択します CTE_Recursiveから )) 、CTE_CLEANRESULT として ( Anchorident、Ident1を識別として選択します cte_recursionresultから 連合 Anchorident、Ident2を識別として選択します cte_recursionresultから )) 選択します cte_idents.ident 、ca_data.xml_valueがnullの場合 その後、cte_idents.ident else ca_data.xml_value end as groupmembers 、deense_rank()over(注文 ca_data.xml_valueがnullの場合 その後、cte_idents.ident else ca_data.xml_value end )GroupIDとして から cte_idents クロス適用 ( cte_cleanresult.ident '、'を選択します CTE_CLEANRESULTから ここで、cte_cleanresult.anchorident = cte_idents.ident XMLパス( '')のcte_cleanresult.identによる注文、タイプ )ca_xml(xml_value) クロス適用 ( ca_xml.xml_value.value( '。'、 'nvarchar(max)'を選択します) )ca_data(xml_value) どこ cte_idents.identはnullではありません 識別による注文; gr.members
c 1
d
3 (e、k)
&&]
i 4 (i)
ソリューション:
サンプルoutput:
識別子 gr_id

a

1
WITH
CTE_Idents
AS
(
    SELECT Ident1 AS Ident
    FROM @T

    UNION

    SELECT Ident2 AS Ident
    FROM @T
)
,CTE_Pairs
AS
(
    SELECT Ident1, Ident2
    FROM @T
    WHERE Ident1 <> Ident2

    UNION

    SELECT Ident2 AS Ident1, Ident1 AS Ident2
    FROM @T
    WHERE Ident1 <> Ident2
)
,CTE_Recursive
AS
(
    SELECT
        CAST(CTE_Idents.Ident AS varchar(8000)) AS AnchorIdent 
        , Ident1
        , Ident2
        , CAST(','   Ident1   ','   Ident2   ',' AS varchar(8000)) AS IdentPath
        , 1 AS Lvl
    FROM 
        CTE_Pairs
        INNER JOIN CTE_Idents ON CTE_Idents.Ident = CTE_Pairs.Ident1

    UNION ALL

    SELECT 
        CTE_Recursive.AnchorIdent 
        , CTE_Pairs.Ident1
        , CTE_Pairs.Ident2
        , CAST(CTE_Recursive.IdentPath   CTE_Pairs.Ident2   ',' AS varchar(8000)) AS IdentPath
        , CTE_Recursive.Lvl   1 AS Lvl
    FROM
        CTE_Pairs
        INNER JOIN CTE_Recursive ON CTE_Recursive.Ident2 = CTE_Pairs.Ident1
    WHERE
        CTE_Recursive.IdentPath NOT LIKE CAST('%,'   CTE_Pairs.Ident2   ',%' AS varchar(8000))
)
,CTE_RecursionResult
AS
(
    SELECT AnchorIdent, Ident1, Ident2
    FROM CTE_Recursive
)
,CTE_CleanResult
AS
(
    SELECT AnchorIdent, Ident1 AS Ident
    FROM CTE_RecursionResult

    UNION

    SELECT AnchorIdent, Ident2 AS Ident
    FROM CTE_RecursionResult
)
SELECT
    CTE_Idents.Ident
    ,CASE WHEN CA_Data.XML_Value IS NULL 
    THEN CTE_Idents.Ident ELSE CA_Data.XML_Value END AS GroupMembers
    ,DENSE_RANK() OVER(ORDER BY 
        CASE WHEN CA_Data.XML_Value IS NULL 
        THEN CTE_Idents.Ident ELSE CA_Data.XML_Value END
    ) AS GroupID
FROM
    CTE_Idents
    CROSS APPLY
    (
        SELECT CTE_CleanResult.Ident ','
        FROM CTE_CleanResult
        WHERE CTE_CleanResult.AnchorIdent = CTE_Idents.Ident
        ORDER BY CTE_CleanResult.Ident FOR XML PATH(''), TYPE
    ) AS CA_XML(XML_Value)
    CROSS APPLY
    (
        SELECT CA_XML.XML_Value.value('.', 'NVARCHAR(MAX)')
    ) AS CA_Data(XML_Value)
WHERE
    CTE_Idents.Ident IS NOT NULL
ORDER BY Ident;

b

2 (b、d、f、j) c 1 (a、c、g、h、l) d 2 k 3 (e、k) 1 (z)
e 3 (e、k)
f 2 (b、d、f、j)
l
z 5
クエリは再帰CTEを使用して、CTE_PAIRSテーブルで定義されているエッジに従うグラフ内のすべてのパスを見つけます。 XMLパスとクロスの場合、各グループの接続された識別子を連結するために適用します。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3