0

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

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

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、存储过程或其他一些逻辑来为所有级别执行相同的操作。输入数据和所需输出将类似于此链接寻找一些建议。

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
4

2 回答 2

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 允许减少结果行。

于 2016-02-18T09:09:44.430 回答
0

具有递归 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
于 2016-02-18T13:21:17.497 回答