简体   繁体   English

使用 SQL 根据各个组的传递/合并分配组号

[英]Using SQL to assign group numbers based on transitive/consolidation of individual groups

Consider the following table考虑下表

create table #table 
(
     Name varchar(100), 
     Group1 bigint, 
     Group2 bigint, 
     Group3 bigint
)

insert into #table values('Adam', 276328, 00001, 0)
insert into #table values('Bob', 276328, 00002, 0)
insert into #table values('Catherine', 927356, 00002, 0)
insert into #table values('Dave', 927356, 00003, 0)
insert into #table values('Eleanor', 927379, 00003, 0)
insert into #table values('Krampus', 927390, 00004, 0)

I'm trying to update Group3 column, with a newly autogenerated group number.我正在尝试使用新自动生成的组号更新Group3列。

For instance, initially the names are pre-grouped as "Adam, Bob", "Catherine, Dave", "Eleanor" and then "Krampus" which is evident from Group 1 .例如,最初将名称预先分组为“亚当、鲍勃”、“凯瑟琳、戴夫”、“埃莉诺”,然后是“Krampus”,这在Group 1中很明显。

Group 2 then groups the Names as "Adam", "Bob & Catherine", "Dave & Eleanor" and then "Krampus" Group 2组然后将姓名分组为“亚当”、“鲍勃和凯瑟琳”、“戴夫和埃莉诺”,然后是“Krampus”

What I'm trying to do is, use Group 1 and Group 2 to assign a new "Group 3" that transitively groups all of them.我想要做的是,使用第 1 组和第 2 组分配一个新的“第 3 组”,将它们全部分组。

Something like "Adam & Bob & Catherine & Dave & Eleanor" because Adam is grouped with Bob on Group 1 and Bob is grouped with Catherine on Group 2 which means, they're all transitively grouped together.类似于“Adam & Bob & Catherine & Dave & Eleanor”,因为 Adam 与 Bob 在第 1 组中分组,而 Bob 与 Catherine 在第 2 组中分组,这意味着,它们都可传递地组合在一起。

An output like:输出如下:

'Adam', 276328, 00001, 00001
'Bob', 276328, 00002, 00001
'Catherine', 927356, 00002, 00001
'Dave', 927356, 00003, 00001
'Eleanor', 927379, 00003, 00001
'Krampus', 927390, 00004, 00002

I've played around with Rank() , Dense_Rank() - but cannot find a way to transitively group all of them.我玩过Rank()Dense_Rank() - 但找不到一种方法来将它们全部分组。

This is a graph walking problem, because A and B could be in group 1. Then A and C could be in group 2. Then C and D could be in group 1.这是一个图行走问题,因为 A 和 B 可以在组 1 中。然后 A 和 C 可以在组 2 中。然后 C 和 D 可以在组 1 中。

That suggests a recursive CTE:这表明递归 CTE:

with cte as (
      select name, group1, group2, convert(varchar(max), ',' + name + ',') as visited, name as grouping
      from t
      union all
      select cte.name, t.group1, t.group2, concat(visited, t.name, ','),
             (case when cte.name < t.name then cte.name else t.name end)
      from cte join
           t
           on cte.group1 = t.group1 or
              cte.group2 = t.group2
      where visited not like '%,' + t.name + ',%'
     )
select name, dense_rank() over (order by min(grouping)) as grp
from cte
group by name;

Here is a db<>fiddle. 是一个 db<>fiddle。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM