我有一个包含两列(Person 和 Item)的数据集,我想基于 column1 生成一个组列(Group),但该组将扩展以包含与第 2 列具有相同值的行。
Sample1 - 因为1和2都有a和b,所以它们被认为是1组。 3 被分开,因为它是唯一包含项目 a 的一个。
人 | 项目 | 团体 |
---|---|---|
1 | a | 1 |
1 | b | 1 |
2 | a | 1 |
2 | b | 1 |
3 | a | 2 |
Sample2 - 因为 1 和 2 有不同的项目,所以它们被视为不同的组。 3 也是独立的,即使它具有相同的“a”项,因为它是它唯一的项。
人 | 项目 | 团体 |
---|---|---|
1 | a | 1 |
1 | b | 1 |
2 | c | 2 |
2 | d | 2 |
3 | a | 3 |
Sample3 - 1 和 2 都有相同的项目,因此它们都被视为 1 组
人 | 项目 | 团体 |
---|---|---|
1 | a | 1 |
1 | b | 1 |
1 | c | 1 |
2 | a | 1 |
2 | b | 1 |
2 | c | 1 |
我发现了类似的帖子,但第二列没有相同的分组/检查机制: 将多列之间相互关联的标识符/值分组
我想我需要基于 Item 进行自连接并循环它,但目前有点卡住了。
提前致谢!
识别每个人的物品组,然后按该组进行分组。
with t (person, item) as (
select 1, 'a' union all
select 1, 'b' union all
select 2, 'a' union all
select 2, 'b' union all
select 3, 'a'
)
, person_to_itemset as (
select person, string_agg(item,',') within group (order by item) as itemset
from t
group by person
)
, itemset_to_group as (
select itemset, row_number() over (order by min(person)) grp
from person_to_itemset
group by itemset
)
select t.*, ig.grp
from t
join person_to_itemset pi on t.person = pi.person
join itemset_to_group ig on pi.itemset = ig.itemset
人 | 项目 | grp |
---|---|---|
1 | a | 1 |
1 | b | 1 |
2 | a | 1 |
2 | b | 1 |
3 | a | 2 |
(请注意,
string_agg
函数仅用于演示目的。为了安全工作,item
列不得包含逗号字符,并且可能在每个人有大量item
时表现不佳。直接分组到集合类型可以是替代方案,不幸的是我实际上不使用 SQL Server 并且不确定它是否支持某些集合,包括分组相等比较的能力,每个 item
表单集或 person
是否也很重要多集。)