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