【问题标题】:How to group/List all nodes of a undirected graph using teradata sql如何使用 teradata sql 对无向图的所有节点进行分组/列出
【发布时间】:2016-02-20 20:57:17
【问题描述】:

我有许多差异的数据。表中的一组无向图(如相邻列表关系,一个节点与所有节点相连),我需要对所有单独的无向图进行分组。

例如:特定无向图的所有节点都将在一个组中,组名将是最小值。节点。

sel d.adj_node, min(d.adj_node) Over (Partition By a.node) as grp
table a 
left join table b
on a.adj_node=b.node
left join table c
on b.adj_node=c.node
​left join table d
​on c.adj_node=d.node​;

现在,我进行了 4.5 次自联接,然后在该查询之上对其进行分区以获得所需的输出。但是进行自我加入 4 5 次会产生性能问题。

因此,需要一些递归 sql、存储过程或其他一些逻辑来为所有级别执行相同的操作。输入数据和所需输出将是这样的link 寻找一些建议。

Input Table

node    adj_node
1       2
2       1
2       3
2       5
2       6
2       7
3       2
3       4
4       3
4       5
4       6
4       7
5       2
5       4
6       2
6       4
6       8
7       2
7       4
8       6
1       1
2       2
3       3
4       4
5       5
6       6
7       7
8       8
10      11
11      10
11      13
11      14
12      13
12      14
13      11
13      12
13      14
14      11
14      12
14      13
10      10
11      11
12      12
13      13
14      14


Output
node    grp
1       1
2       1
3       1
4       1
5       1
6       1
7       1
8       1
10      10
11      10
12      10
13      10
14      10

【问题讨论】:

    标签: sql stored-procedures teradata recursive-query undirected-graph


    【解决方案1】:

    我只记得在临时表上使用更新之前我做了类似的事情。

    实现这一点的最佳方法是其中包含循环的存储过程:

    CREATE VOLATILE TABLE vt_tab AS
     (
       SELECT DISTINCT NODE , adj_node, NODE AS grp
       FROM tab AS t1
       WHERE adj_node <> NODE
     ) WITH DATA
    ON COMMIT PRESERVE ROWS
    ;
    
    -- REPEAT this update UNTIL activity_count = 0
    UPDATE vt_tab FROM
     ( 
      SELECT t2.NODE, MIN(t1.grp) AS mingrp
      FROM vt_tab AS t1 JOIN vt_tab AS t2
      ON t1.adj_node = t2.NODE
      AND t1.grp < t2.grp
      GROUP BY t2.NODE
     ) x
    SET grp = mingrp
    WHERE vt_tab.NODE = x.NODE
    ;
    
    --get the final result
    SEL DISTINCT NODE,grp
    FROM vt_tab
    ORDER BY 1
    ;
    

    递归可能是可能的,但它很可能会破坏您的线轴,因为您需要重复 m:n 连接,并且只有最终的 Select 允许减少结果行。

    【讨论】:

    • @Biti - 然后您需要通过选择此答案左侧的勾号将其标记为答案
    • @dnoeth - 逻辑/代码对我来说工作正常,但我发现很难理解更新内部的逻辑。您能简要解释一下更新中使用的算法吗?
    • @Biti:只需运行 SELECT 部分,您将看到它模拟了递归,加入层次结构中的两个级别,找到每个节点的最小 grp 值并将其分配给所有节点行
    【解决方案2】:

    具有递归 CTE 的解决方案:

    with cte as
    (
        select node as node, node as grp
        from Tabl_1
        Union all
        select C.node, T.adj_node
        from CTE C inner join Tabl_1 T on C.grp = T.node
        where T.adj_node < C.grp
    )
    
    select node, MIN(grp) as grp 
    from cte
    group by node
    order by node
    

    == 编辑 1 == 这是一个反映您观点的新版本。

    with cte as
    (
        select node as node, node as grp, ',' + CAST(node as varchar(max)) + '-' + CAST(node as varchar(max)) + ',' as pair
        from Tabl_1
        Union all
        select C.node, T.adj_node, C.pair + CAST(C.node as varchar(max)) + '-' + CAST(T.adj_node as varchar(max)) + ','
        from CTE C inner join Tabl_1 T on C.grp = T.node
        where C.pair not like '%,' + CAST(C.node as varchar(max)) + '-' + CAST(T.adj_node as varchar(max)) + ',%'
    )
    
    select node, MIN(grp) as grp 
    from cte
    group by node
    order by node
    

    【讨论】:

    • 感谢您的建议。它工作正常,但我得到了一组无向图,它使用您的逻辑创建两个组而不是一个组。我无法弄清楚为什么它要创建 2 个组。你能告诉我这个问题吗?请找到输入数据和图表。 link
    • @Biti 我在编辑 1 中更改了我的脚本以考虑您的评论。
    猜你喜欢
    • 2016-02-07
    • 2023-01-24
    • 2012-03-07
    • 2021-11-17
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 2023-01-18
    • 2012-04-22
    相关资源
    最近更新 更多