Group All Related Records in Many to Many Relationship, SQL graph connected components

后端 未结 6 883
遥遥无期
遥遥无期 2020-12-08 21:48

Hopefully I\'m missing a simple solution to this.

I have two tables. One contains a list of companies. The second contains a list of publishers. The mapping between

6条回答
  •  爱一瞬间的悲伤
    2020-12-08 22:42

    Here is my solution SQL Fiddle

    The nature of the relationships require looping as I figure.


    Here is the SQL:

    --drop TABLE Table1
    
    CREATE TABLE Table1
        ([row] int identity (1,1),GroupID INT NULL,[Company] varchar(2), [Publisher] varchar(2))
    ;
    
    INSERT INTO Table1
        (Company, Publisher)
    select
        left(newid(), 2), left(newid(), 2)
    
    declare @i int = 1
    
    while @i < 8
    begin
        ;with cte(Company, Publisher) as (
            select
                left(newid(), 2), left(newid(), 2)
            from Table1
        )
        insert into Table1(Company, Publisher)
        select distinct c.Company, c.Publisher
        from cte as c
        where not exists (select * from Table1 as t where t.Company = c.Company and t.Publisher = c.Publisher)
    
        set @i = @i + 1
    end;
    
    
    CREATE NONCLUSTERED INDEX IX_Temp1 on Table1 (Company)
    CREATE NONCLUSTERED INDEX IX_Temp2 on Table1 (Publisher)
    
    declare @counter int=0
    declare @row int=0
    declare @lastnullcount int=0
    declare @currentnullcount int=0
    
    WHILE EXISTS (
      SELECT *
      FROM Table1
      where GroupID is null
      )
    BEGIN
        SET @counter=@counter+1
        SET @lastnullcount =0
    
        SELECT TOP 1
            @row=[row]
        FROM Table1
        where GroupID is null
        order by [row] asc
    
        SELECT @currentnullcount=count(*) from table1 where groupid is null
        WHILE @lastnullcount <> @currentnullcount
        BEGIN
            SELECT @lastnullcount=count(*)
            from table1
            where groupid is null 
    
            UPDATE Table1
            SET GroupID=@counter
            WHERE [row]=@row
    
            UPDATE t2
            SET t2.GroupID=@counter
            FROM Table1 t1
            INNER JOIN Table1 t2 on t1.Company=t2.Company
            WHERE t1.GroupID=@counter
            AND t2.GroupID IS NULL
    
            UPDATE t2
            SET t2.GroupID=@counter
            FROM Table1 t1
            INNER JOIN Table1 t2 on t1.publisher=t2.publisher
            WHERE t1.GroupID=@counter
            AND t2.GroupID IS NULL
    
            SELECT @currentnullcount=count(*)
            from table1
            where groupid is null
        END
    END
    
    SELECT * FROM Table1
    

    Edit: Added indexes as I would expect on the real table and be more in line with the other data sets Roman is using.

提交回复
热议问题