我有一个返回两列的查询,它代表两个实体(直接或间接)之间的关系,例如右边图表中显示的关系将由右边表格中的数据表示: / p>
| From | To | 1 3 4
|------|----| o----o----o
| 1 | 3 | / \
| 1 | 4 | / \
| 1 | 5 | 2 o o 5
| 2 | 3 |
| 2 | 4 |
| 2 | 5 |
| 3 | 4 | 6 7
| 3 | 5 | o----o
| 6 | 7 |
我想要做的是将这些数据分组为多个集合,等于关系描述的不同图表的数量(在上例中为2集)。
此分组可以作为数据库查询(T-SQL)的一部分或数据在内存(C#)中发生。
答案 0 :(得分:1)
它可能不漂亮,但这会正确地对顶点进行分组,并且只需要边缘作为起点。请注意,边的顶点顺序无关紧要。
-- Sample data.
declare @Edges as Table ( Vertex1 Int, Vertex2 Int );
insert into @Edges ( Vertex1, Vertex2 ) values
( 1, 3 ), ( 3, 4 ), ( 3, 2 ), ( 3, 5 ),
( 6, 7 );
select * from @Edges;
-- Create a working table that assigns each vertex to a unique "set".
declare @Sets as Table ( SetId Int, Vertex Int );
insert into @Sets ( SetId, Vertex )
select Row_Number() over ( order by Vertex ), Vertex from (
select distinct Vertex1 as Vertex from @Edges
union
select distinct Vertex2 from @Edges ) as PH;
select * from @Sets;
-- Update the working table to group vertexes into sets:
-- For each vertex update the SetId to the minimum SetId of all of the vertexes one edge away.
-- Repeat until nothing changes.
declare @UpdatedRows as Int = 42;
while @UpdatedRows > 0
begin
update NS
set SetId = MinSetId
from (
select S.SetId, S.Vertex,
( select Min( SetId ) from @Sets where Vertex in (
select S.Vertex union
select Vertex1 from @Edges where Vertex2 = S.Vertex union
select Vertex2 from @Edges where Vertex1 = S.Vertex )
) as MinSetId
from @Sets as S ) as NS
where SetId != MinSetId;
set @UpdatedRows = @@RowCount;
select * from @Sets; -- Show the work as it progresses.
end
-- The SetId values can be collapsed using Dense_Rank .
select Dense_Rank() over ( order by SetId ) as SetId, Vertex
from @Sets;