将所有相似人物收集到一组

Dim*_* Ha 7 sql-server t-sql graph sql-server-2012

我有一个人有几个 ID。其中一些在 Id1 列中,其中一些在 Id2 中。我想将所有相同的人 ID 收集到一组。

如果 id1=10,则与 id2=20 在同一行。所以这意味着id1=10的人与id2=20是同一个人。

输入和输出示例:

输入

Id1     Id2
---     ---
10      20
10      30
30      30
10      40

50      70
60      50
70      70 
Run Code Online (Sandbox Code Playgroud)

输出

NewId   OldId
-----   -----
1       10
1       20
1       30
1       40

2       50
2       60
2       70
Run Code Online (Sandbox Code Playgroud)

San*_*ndr 3

最好以迭代的方式进行这样的计算。

这种解决方案的“问题”是,如果源表很大,输出表将包含所有行。但实际上,这也是好处:在源表很大的情况下,这样的代码将比递归运行得更快。


if object_id('tempdb..#src') is not null drop table #src;
create table #src (id1 int not null, id2 int)

if object_id('tempdb..#rez') is not null drop table #rez;
create table #rez (id int not null, chainid int not null);

declare @chainId int;

insert #src
values (10, 20), (10, 30), (30, 30), (10, 40), (50, 70), (60, 50), (70, 70)
--values (4457745,255714),(4457745,2540222),(2540222,4457745),(255714,4457745)

set @chainId = 1

while 1 = 1
begin
    insert #rez(id, chainid)
    select top 1 id1, @chainId
    from #src
    where
        Id1 NOT IN (select Id from #rez)
        and id2 NOT IN (select Id from #rez)

    if @@rowcount = 0 break

    while 1 = 1
    begin
        insert #rez(id, chainid)

        select id1, @chainid
        from #src
        where
            id2 in (select id from #rez where chainid = @chainId)
            and id1 not in (select id from #rez where chainid = @chainId)

        union

        select id2, @chainId
        from #src
        where
            id1 in (select id from #rez where chainid = @chainId)
            and id2 not in (select id from #rez where chainid = @chainId)

        if @@rowcount = 0 break
    end

    select @chainId = @chainId + 1
end

select [NewId] = chainid, OldID = id
from #rez 
order by 1, 2;
Run Code Online (Sandbox Code Playgroud)

在一些细节上,脚本的“逻辑”如下:

  • 设置新 ID (chainid) 初始值(例如 1)

    • 获取第一个尚未找到的条目(外部循环)

      • 查找并存储与其相关的所有内容(在两列中)(内部循环)
    • 增加新的ID

    • 查找不在结果表中的下一个条目

    • 继续直到有数据可以工作

  • 返回排序结果