我有一个简单的加权图
A
1 / \\ 0.5
/ \\0.5
B C
假设这描述了一个家庭,A是父亲,B是儿子而C是母亲。假设B正在大学学习,A已经为他买了一套公寓。 A与C居住在共同拥有的房子里,50-50。
我想将图形转换为树,从A:ie开始。
图表和生成的树可能更精细但我希望你能得到更全面的图片。
在SQL Server 2005上我有
Drop Table #graph;
Create Table #graph
(FirstVertex VarChar(1) Not Null,
SecondVertex VarChar(1) Not Null,
Weight float);
Insert #graph Values('A','B',1);
Insert #graph Values('A','C',0.5);
Insert #graph Values('C','A',0.5);
我正在使用以下公用表表达式遍历图表,从'A'开始:
With GraphRecursion (FirstVertex, SecondVertex, Weight, Level)
As
(
Select FirstVertex, SecondVertex, Weight, 0 As Level
From #graph
Where FirstVertex='A'
Union all
Select a.FirstVertex, a.SecondVertex, a.Weight, b.Level+1
From #graph a
Inner Join GraphRecursion b
On a.FirstVertex=b.SecondVertex --And b.Level<=1
)
Select * From GraphRecursion;
这会导致
Msg 530, Level 16, State 1, Line 11
The statement terminated. The maximum recursion 100 has
been exhausted before statement completion.
通过取消注释And b.Level<=1
来限制递归级别会得到预期的结果,但这显然对任何实际用途都没有用。
有没有办法引用前面的迭代,以便在上面的例子中边缘(即FirstVertex,SecondVertex对)不会重复?
答案 0 :(得分:3)
您可以在另一列中构建受访节点列表,然后阻止在递归中重新访问它们。这样的事情(不确定我选择了正确的列):
With GraphRecursion (FirstVertex, SecondVertex, Weight, Level,Nodes)
As
(
Select FirstVertex, SecondVertex, Weight, 0 As Level,CONVERT(varchar(8000),':' + FirstVertex + ':' + SecondVertex + ':')
From #graph
Where FirstVertex='A'
Union all
Select a.FirstVertex, a.SecondVertex, a.Weight, b.Level+1,b.Nodes + ':' + a.SecondVertex + ':'
From #graph a
Inner Join GraphRecursion b
On a.FirstVertex=b.SecondVertex --And b.Level<=1
where not b.Nodes like '%:' + a.SecondVertex + ':%'
)
Select * From GraphRecursion;
如果你想避免每次重新遍历边缘,而不是重新访问一个顶点,你就可以建立你的链接,例如: ':'+ FirstVertex +'@'+ SecondVertex +':'。在这些例子中,我只是使用':'和'@'作为不出现在顶点名称中的字符。 (避免重新遍历 - 更接近b.Level&lt; = 1的结果,但不完全):
With GraphRecursion (FirstVertex, SecondVertex, Weight, Level,Nodes)
As
(
Select FirstVertex, SecondVertex, Weight, 0 As Level,CONVERT(varchar(8000),':' + FirstVertex + '@' + SecondVertex + ':')
From #graph
Where FirstVertex='A'
Union all
Select a.FirstVertex, a.SecondVertex, a.Weight, b.Level+1,b.Nodes + ':' + a.FirstVertex + '@' + a.SecondVertex + ':'
From #graph a
Inner Join GraphRecursion b
On a.FirstVertex=b.SecondVertex --And b.Level<=1
where not b.Nodes like '%:' + a.FirstVertex + '@' + a.SecondVertex + ':%'
)
(请注意,原始b.Level&lt; = 1版本从此示例中获取5行,而不是上面第二个示例中的4行)。但我相信这是正确的。 b.Level&lt; = 1版本返回a-&gt; c,c-&gt; a,a-&gt; c的2级行,我认为不需要