2017-10-02 9 views
0

2つのエンティティ間の関係を直接的または間接的に表す2つの列を返すクエリがあります。たとえば、右側のグラフに表示されるリレーションシップは、右テーブル:クエリの結果をユニークなセットに分割する

| 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 | 

私は何をしたいグループは、関係(上記の例ではSO 2セット)によって記載異なるグラフの数に等しくセットの数、にこのデータです。

このグループは、データベースクエリ(T-SQL)の一部として、またはデータがメモリ(C#)に格納されると発生する可能性があります。

+0

私は1対5があなたの例で間違いだと思いますか?またはそうでない場合は、2から4の間でなければなりません。 – Neil

+0

ありがとうNeil、私は2から4の関係を見逃していました。私はそのリンクを含むように質問を更新しました。 – Darren

+1

https://en.wikipedia.org/wiki/Connected_component_(graph_theory) – Backs

答えて

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; 
+0

私はこれをデータアクセスコード(C#)と同様の方法で解決しましたが、SQLを嫌う心のために@HABOに感謝します! – Darren

関連する問題