0

I have data for many diff. set of undirected graphs in a table (like adjacent list relationship, one node is connected which all node) and I need to group all individual undirected graphs.

Eg: all nodes of the particular undirected graphs will be in a group & group name will be the min. of the node.

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​;

Now, I am doing a self-join for 4,5 times and then on top that query doing partitioning it to get the desired output. But doing self-join 4 5 times is creating performance issue.

So, need some recursive sql, stored procedure or some other logic to do the same for all levels. Input Data & Required Output will be like this link Looking for some suggestions.

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
ITIB
  • 353
  • 6
  • 16

2 Answers2

1

I just remembered that I did something similar before using updates on a temp table.

The best way to implement this would be a Stored Procedure with a loop in it:

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
;

Recursion might be possible, but there's a high probability that it will blow your spool because you need repeated m:n joins and only the final Select allows to reduce the result rows.

dnoeth
  • 59,503
  • 4
  • 39
  • 56
  • @Biti - Then you need to mark it as answer by selecting the tick mark to the left of this answer – Pரதீப் Feb 20 '16 at 13:08
  • @dnoeth - logic/code is working fine for me but I am finding it diffucult to understand the logic inside update. Can you explain the algo briefly that is being used inside the update ? – ITIB Feb 23 '16 at 07:27
  • @Biti: Simply run the SELECT part and you will see that this mimics the recursion, *join two levels in the hierarchy, find the smallest `grp` value per Node and assign it to all rows* – dnoeth Feb 23 '16 at 07:47
0

A solution with a recursive 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

== EDIT 1 == Here is a new version to reflect your point.

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
Polux2
  • 552
  • 3
  • 12
  • Thanks for suggesting. Its working fine, but I got one set of an undirected graph where it's creating two groups instead of one using your logic. I am not able to figure out the issue why it's creating 2 groups. Can you please tell me the issue. Please find the input data & graph diagram. [link](http://www.digitalcrunch.in/uploads/Input.xls) – ITIB Feb 19 '16 at 08:56
  • @Biti I have changed my script in Edit 1 to take in account your remark. – Polux2 Feb 20 '16 at 11:13