如何在 BigQuery 中给定大图生成连接组件?

问题描述 投票:0回答:2

我想使用 BigQuery 生成图表的“连接组件”。 给出下图(由连接的节点对表示):

(E1, E2) (E2, E3) (E3, E4) (E4, E5)

我们可以得出结论,所有这些组件都是连接的,因此代表一个连接的组件:

(E1, E2, E3, E4, E5)

以下是用于生成图的连通分量的传统算法:
广度优先搜索

深度优先搜索 我最初的想法是重新创建匹配的节点对,以便所有实体最终都指向一个公共节点(通过使子节点指向其祖先节点)。因此,如果 (E1, E2) 是一对并且 (E2, E3) 是一对。我可以编写 SQL 逻辑来创建一个新对 (E1, E3),然后我可以丢弃 (E2, E3)。

这是一个更深入的示例:

输入:

(E1, E2) (E2, E3) (E3, E4) (E4, E5)

迭代 1:

(E1, E2) (E1, E3) which replaces (E2, E3) (E2, E4) which replaces (E3, E4) (E3, E5) which replaces (E4, E5)

迭代 2:

(E1, E2) (E1, E3) (E1, E4) which replaces (E2, E4) (E1, E5) which replaces (E3, E5)

我很快意识到,当图很大时,这个过程需要很长时间,因为我们一次只执行一跳。

是否可以根据 BigQuery 表中的给定匹配对更快地生成连接组件?

输入:

|--------------------|------------------| | Entity 1 | Entity 2 | |--------------------|------------------| | E1 | E2 | |--------------------|------------------| | E2 | E3 | |--------------------|------------------| | E3 | E4 | |--------------------|------------------| | E4 | E5 | |--------------------|------------------|

所需输出:

我想编写一个查询,读取上面的输入表并输出以下内容:

|--------------------|------------------| | Entity | Group | |--------------------|------------------| | E1 | 1 | |--------------------|------------------| | E2 | 1 | |--------------------|------------------| | E3 | 1 | |--------------------|------------------| | E4 | 1 | |--------------------|------------------| | E5 | 1 | |--------------------|------------------|

这在 BigQuery 中可能吗?

sql google-cloud-platform google-bigquery
2个回答
2
投票
https://en.wikipedia.org/wiki/Recursive_join

更新

:现在支持递归 CTE,因此这个答案大部分已过时。 但是由于 BigQuery 并不直接支持这一点, 你能做的就是重复将表与其自身连接起来, 创建一个新的连接组件表并执行此操作 直到组件数量不再变化。

类似:

select a, min(if(c > a, a, c)) c from (select x.a, y.c from data x join data y on x.c = y.a) group by a;

这将根据其自身值和连接值的 id 的最小值为每个值分配组件 id 
c

每次运行后,检查

select count(distinct c) from data;

一旦停止变化 - 你就完成了。


0
投票
ROW_NUMBER

配合窗口函数来制作。


什么是窗函数。

OVER ( [ <PARTITION BY clause> ] [ <ORDER BY clause> ] [ <ROW or RANGE clause> ] )

  
在应用关联的窗口函数之前确定行集的分区和排序。也就是说,OVER 子句定义查询结果集中的窗口或用户指定的行集。然后,窗口函数计算窗口中每一行的值。

这样你就可以通过
Entity1

 来制作行号

SELECT Entity1, ROW_NUMBER() OVER(partition by Entity1) Group FROM T

行号

© www.soinside.com 2019 - 2024. All rights reserved.