SQL Server图查询:获取节点所在完整连通网络的方案
解决SQL Server有向图全连通节点查询问题
我们在SQL Server 2019中基于有向图数据模型定义了NODE表nodes和EDGE表connections,需要实现一个表值函数,使得查询连通图中的任意节点(如A、F)时,都能返回该节点所属的完整连通网络节点集合(A、B、C、D、E、F)。
现有函数问题
当前实现的calculateNetworkForNode函数仅支持查询指定节点的下游可达节点:
- 查询节点A可返回所有下游节点及自身,但查询节点F仅能返回自身;
- 若节点F存在其他入边,函数会失效。
原函数代码如下:
CREATE FUNCTION calculateNetworkForNode( @DiscoverScenarioFor VARCHAR(15) ) returns @network TABLE (base varchar(15), pathToNode varchar(max), networkMember varchar(15)) begin INSERT @network SELECT base, pathToNode, networkMember FROM ( SELECT nodes.name as base, STRING_AGG(nodes2.name, '->') WITHIN GROUP (GRAPH PATH) AS pathToNode, LAST_VALUE(nodes2.name) WITHIN GROUP (GRAPH PATH) AS networkMember FROM nodes, connections FOR PATH, nodes FOR PATH AS nodes2 WHERE MATCH(SHORTEST_PATH(nodes(-(connections)->nodes2)+)) AND nodes.name = @DiscoverScenarioFor ) AS Q WHERE Q.networkMember != @DiscoverScenarioFor insert into @network (base, pathToNode, networkMember) values (@DiscoverScenarioFor, null, @DiscoverScenarioFor) RETURN end
解决方案思路与实现
要实现全连通节点查询,需将有向图的单向遍历改为双向无向遍历,即同时支持正向(下游)和反向(上游)的边遍历,具体修改如下:
修改后的函数代码
CREATE FUNCTION calculateFullConnectedNetworkForNode( @DiscoverScenarioFor VARCHAR(15) ) returns @network TABLE (base varchar(15), pathToNode varchar(max), networkMember varchar(15)) begin -- 插入双向可达的节点(排除自身,后续单独插入) INSERT @network SELECT DISTINCT @DiscoverScenarioFor as base, STRING_AGG(nodes2.name, '->') WITHIN GROUP (GRAPH PATH) AS pathToNode, LAST_VALUE(nodes2.name) WITHIN GROUP (GRAPH PATH) AS networkMember FROM nodes, connections FOR PATH, nodes FOR PATH AS nodes2 WHERE MATCH(SHORTEST_PATH(nodes((-(connections)->nodes2)|(<-(connections)-nodes2))+)) AND nodes.name = @DiscoverScenarioFor AND LAST_VALUE(nodes2.name) WITHIN GROUP (GRAPH PATH) != @DiscoverScenarioFor -- 插入自身节点 insert into @network (base, pathToNode, networkMember) values (@DiscoverScenarioFor, null, @DiscoverScenarioFor) RETURN end
关键修改说明
- 双向遍历匹配:将原MATCH语句中的
nodes(-(connections)->nodes2)+改为nodes((-(connections)->nodes2)|(<-(connections)-nodes2))+,其中|表示逻辑或,允许正向(->)和反向(<-)两种边遍历方向,实现全连通查询。 - 去重处理:添加
DISTINCT关键字,避免同一节点通过不同路径被多次插入结果表。 - 保留原有字段:维持
base、pathToNode、networkMember字段结构,兼容原有业务逻辑。
辅助CSV转换函数修改
若辅助函数基于原函数结果生成CSV,只需将调用的函数替换为calculateFullConnectedNetworkForNode,并确保在拼接CSV前对networkMember字段做去重处理(例如使用DISTINCT关键字筛选后再拼接)。
内容的提问来源于stack exchange,提问作者János Veres
相关产品推荐
相关产品推荐

