cómo encontrar todos los subgrafías conectados de un gráfico no dirigido
Problema:
dada una tabla con dos columnas que contienen identificadores, encuentran todos los grupos de identificadores que están conectados a cada uno Otro.
Ejemplo Tabla:
id | identificador1 | identificer2 |
---|---|---|
&] 1 | a | c |
2 | b | f |
[] | g4 | |
h | 5 | |
d | f | |
e | k | 8 |
9 | l | |
Deseed Salida: | ||
identificador | gr_id |
(a, c, g, h, l) | d | |
---|---|---|
e | 3 | |
[&] | f2 | (b, d, f, j) |
g | 1(a, c, g, h, l) | |
1 | (a, c, g, h, l) | |
2 | (b, d, f, j) | [&] &&]k |
(e, k) | [&] | l1 |
[y] &&] | i | 4 |
Solución: | el La siguiente consulta utiliza una sola consulta recursiva para encontrar todas las subgrafías conectadas: | |
con Cte_idents COMO ( Seleccione Ident1 como ident De @T UNIÓN Seleccione Ident2 como ident De @T ) , Cte_pairs COMO ( Seleccione Ident1, Ident2 De @T Donde ident1 & lt; & gt; Ident2 UNIÓN Seleccione Ident2 como Ident1, Ident1 como Ident2 De @T Donde ident1 & lt; & gt; Ident2 ) , Cte_recursive COMO ( SELECCIONAR Cast (cte_idents.ident como varchar (8000)) como anclaje , Ident1 , Ident2 , Cast (',' ident1 ',' ident2 ',' como varchar (8000)) como identpath , 1 como lvl DE Cte_pairs Inner Join CTE_IDENTS en cte_idents.ident = cte_pairs.ident1 Unión todos SELECCIONAR Cte_recursive.anchorident , Cte_pairs.ident1 , Cte_pairs.ident2 , Cast (CTE_recursive.identPath CTE_Pairs.ident2 ',' como Varchar (8000)) como IdentPath , Cte_recursive.lvl 1 como lvl DE Cte_pairs Inner Join cte_recursive en cte_recursive.ident2 = cte_pairs.ident1 DÓNDE Cte_recursive.identpath no como el cast ('%,' cte_pairs.ident2 ',%' como Varchar (8000)) ) , Cte_recursionResult COMO ( Seleccione AnchorRident, Ident1, Ident2 De cte_recursive ) , Cte_cleanResult COMO ( Seleccione AnchorRident, ident1 como identificación De cte_recursionResult UNIÓN Seleccione AnchorRident, Ident2 como identificación De cte_recursionResult ) SELECCIONAR Cte_idents.ident , Caso cuando ca_data.xml_value es nulo Entonces cte_idents.ident else CA_DATA.XML_VALUE END ASMERMBERS , Dense_rank () over (ordenar por Caso cuando ca_data.xml_value es nulo Entonces cte_idents.ident else CA_DATA.XML_VALUE END ) Como groupid DE Cte_idents Aplicar cruzado ( Seleccione CTE_CleAnresult.ident ',' De cte_cleanResult Donde cte_cleanResult.anchorident = cte_idents.ident Pedido de cte_cleanResult.ident para ruta xml (''), tipo ) Como ca_xml (xml_value) Aplicar cruzado ( Seleccione CA_XML.XML_VALUE.VALUE ('.', 'Nvarchar (max)') ) Como ca_data (xml_value) DÓNDE Cte_idents.ident no es nulo Orden por identificación; | muestra Salida: | |
identificador | gr_id | gr.members |
a | 1 | (A, C, C, G, H, L) |
b | 2 | (B, D, F, J) |
1 (a, c, g, h, h, l)
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;
e 3
syle s, ando] &&] | g | 1 |
---|---|---|
h | 1 | (a, c, g, h, l) &&] |
4 | (i) | |
2 | (b, d, j) | [&] [&] [&] &&]k |
(e, k) | &] | z |
(z) | La tabla CTE_idents contiene todos los identificadores únicos en el gráfico. | la tabla CTE_CleanResult extrae los identificadores conectados para cada identificador de ancla La ruta XML y la cruz se aplican para concatenar los identificadores conectados para cada grupo.dense_rank () se usa para asignar ID de grupo únicas a cada grupo. |
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3