SQL 中两列的标签组(如果可能,BigQuery SQL)

Labelling groups of two columns in SQL (BigQuery SQL if possible)

给定一个 table

     name  ip 
A = |A     1  |
    |B     1  |
    |C     1  |
    |B     2  |
    |C     2  |
    |D     3  |
    |E     2  |

如果任何两个名称共享相同的 ip,则它们属于同一组。具有相同名称的 ip 也属于同一组。如果您找到 ip 1, {A, B, C} 的所有名称,那么您应该在同一组 {1,2} 中包含与 {A,B,C} 关联的所有 ip,然后再包含所有具有这些 ip 的名称还没有包括 {E} 等等。在此特定示例中,{A,B,C,E} x {1, 2} 中的任何内容都属于同一组。上述 table 的结果将是

     name  ip  group
A = |A     1     1    |
    |B     1     1    |
    |C     1     1    |
    |B     2     1    |
    |C     2     1    |
    |D     3     2    |
    |E     2     1    |

明确一点:

如果名称 A、B 和 C 都是 ip 1,那么它们被组合在一起,您应该

A, 1 = group1
B, 1 = group1
C, 1 = group1

如果名字 A、B 也共享 ip 2,那么他们不应该创建一个新组,而应该像这样在同一个组中:

A, 1 = group1
B, 1 = group1
C, 1 = group1
A, 2 = group1
B, 2 = group1

目标是在 Google BigQuery SQL 中解决这个问题。

到目前为止我有

select ip, row_number() over () as group,
GROUP_CONCAT(name,',') as names,
from A
group by ip

生成一个 ip 的所有名称并给出一个组,但没有找到一个名称的所有 ip 或找到包含所有名称和 ip 的所有对的组。

请注意,您可以使用拆分来访问连接的名称(在本例中为“,”)。

更新 - 这称为传递闭包。如果这太难了,展示如何只进行传递闭包的第一次迭代(如何找到与每个 ip 关联的所有名称相关联的所有 ip)并将它们标记为组就足够了。

这是我第一次迭代的解决方案。有点长,可能会改进,但这是我的。

步骤 1.

select name, nest(ip) ips, group_concat(string(ip)) sip from 
(select 'a' name, 1 ip),
(select 'b' name, 1 ip),
(select 'c' name, 1 ip),
(select 'b' name, 2 ip),
(select 'c' name, 2 ip),
(select 'd' name, 3 ip),
(select 'e' name, 2 ip)
group by name

将结果存储在临时 table x

第 2 步

select a.name name, group_concat(b.name) as cluster from (
select a.name, b.name from (
select a.*, b.* from dataset.x a cross join dataset.x b
) omit record if every(not b.sip contains string(a.ips))
group by 1, 2 order by 1, 2) group by 1

临时存储结果 table y

步骤 3.

select cluster from (
select group_concat(part) cluster from (
select name, part from (
select a.name name, split(b.cluster) part 
from dataset.y a cross join dataset.y b
where b.cluster contains a.name) group by 1, 2 order by 1, 2) 
group by name) group by cluster

这应该会产生所有唯一的集群,即

a,b,c,e
d