我有一个SQL服务器表,其中每一行表示图网络中的一条边。FromNodeID和ToNodeID是指向节点表的外键,其架构如下:
CREATE TABLE #Edges (
EdgeID int identity (1,1),
FromNodeID int,
ToNodeID int
);
INSERT INTO #Edges (FromNodeID, ToNodeID) VALUES
(1,2),
(1,3),
(1,4),
(2,3),
(3,5),
(4,5),
(5,6);
现在,如果我将每条边都视为有向的(即单向的),那么很容易计算出我可以直接从任何节点到达的所有节点。我会给FromNodeID列添加一个索引,然后运行以下查询:
SELECT ToNodeID FROM #Edges WHERE FromNodeID = 3
结果: 5
但是如果我想将每个边视为单向,那么最好的表/查询结构是什么呢?即从节点3开始,我想获得以下结果:
结果:1、2、5
我能想到的最简单的方法是在ToNodeID列中添加一个额外的索引,然后运行如下查询:
SELECT ToNodeID FROM #Edges WHERE FromNodeID = 3
UNION SELECT FromNodeID FROM #Edges WHERE ToNodeID = 3;
但是这显然涉及到从两个查询中组合结果集,似乎不太高效 - 是否有更好的方法可以在单个查询中编写此操作?(请注意,我不想再将反向边插入表中 - 我需要能够在运行时将边视为有向或无向)。感谢任何建议!
#Edges
从具有FromNodeID = ToNodeID的情况中获得保护,则您的UNION版本将从使用UNION ALL
而不是UNION
中获胜。即使允许自引用节点,您最好使用SELECT ... WHERE FromNodeID = 3 AND ToNodeID <> 3 UNION ALL SELECT ... WHERE FromNodeID <> 3 AND ToNodeID = 3 UNION ALL SELECT 3 FROM #Edges WHERE FromNodeID = 3 AND ToNodeID = 3
,但仅当您不需要对节点进行排序时(否则它似乎比您的版本性能更差)。 - Andriy M