在BigQuery中给定大图的情况下,如何生成连接的组件?

时间:2018-09-10 20:41:17

标签: sql google-cloud-platform google-bigquery

我想使用BigQuery生成图的connected components

给出下面的图(以连接的节点对表示):

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

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

(E1, E2, E3, E4, E5)

以下是用于生成图的连接部分的传统算法:Breadth-first searchDepth-first search

我最初的想法是重新创建匹配的节点对,以使所有实体最终都指向一个公共节点(通过使子节点指向其祖先节点)。因此,如果(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中这可能吗?

2 个答案:

答案 0 :(得分: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

Row_number

答案 1 :(得分:0)

您需要的是递归联接: https://en.wikipedia.org/wiki/Recursive_join

但是由于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;

一旦停止更改-您就完成了。