多父树(或有向图)实现sql server 2005
我需要在 SQL Server 2005 上实现多父树(或有向图)。 我读过几篇文章,但大多数都使用具有独特根的单亲树,如下所示。
-My PC
-Drive C
-Documents and Settings
-Program Files
-Adobe
-Microsoft
-Folder X
-Drive D
-Folder Y
-Folder Z
在这个例子中,一切都源自根元素(我的电脑)。
在我的例子中,一个孩子可以有超过 1 个父母,如下所示:
G A
\ /
B
/ \
X C
/ \
D E
\ /
F
所以我有以下代码:
create table #ObjectRelations
(
Id varchar(20),
NextId varchar(20)
)
insert into #ObjectRelations values ('G', 'B')
insert into #ObjectRelations values ('A', 'B')
insert into #ObjectRelations values ('B', 'C')
insert into #ObjectRelations values ('B', 'X')
insert into #ObjectRelations values ('C', 'E')
insert into #ObjectRelations values ('C', 'D')
insert into #ObjectRelations values ('E', 'F')
insert into #ObjectRelations values ('D', 'F')
declare @id varchar(20)
set @id = 'A';
WITH Objects (Id, NextId) AS
( -- This is the 'Anchor' or starting point of the recursive query
SELECT rel.Id,
rel.NextId
FROM #ObjectRelations rel
WHERE rel.Id = @id
UNION ALL -- This is the recursive portion of the query
SELECT rel.Id,
rel.NextId
FROM #ObjectRelations rel
INNER JOIN Objects -- Note the reference to CTE table name (Recursive Join)
ON rel.Id = Objects.NextId
)
SELECT o.*
FROM Objects o
drop table #ObjectRelations
返回以下 SET
Id NextId
-------------------- --------------------
A B
B C
B X
C E
C D
D F
E F
: 预期结果 SET:
Id NextId
-------------------- --------------------
G B
A B
B C
B X
C E
C D
D F
E F
请注意,关系 G->B 缺失,因为它要求一个起始对象(这对我也不起作用,因为我从一开始就不知道根对象)并使用 A 作为起始点将忽略 G->B 关系。
因此,这段代码在我的情况下不起作用,因为它要求一个起始对象,这在单父树中很明显(将始终是根对象)。 但在多父树中,您可以有超过 1 个“根”对象(如示例中,G 和 A 是“根”对象,其中根是没有父级(祖先)的对象)。
所以我有点卡在这里......我需要修改查询以不要求起始对象并递归遍历整个树。 我不知道 (Id, NextId) 实现是否可能......可能我需要使用某种关联矩阵、邻接矩阵或其他什么来将它存储为图形(请参阅 http://willets.org/sqlgraphs.html)。
有什么帮助吗? 你们觉得怎么样? 非常感谢您抽出宝贵的时间=)
干杯!
I need to implement a multi-parented tree (or digraph) onto SQL Server 2005.
I've read several articles, but most of them uses single-parented trees with a unique root like the following one.
-My PC
-Drive C
-Documents and Settings
-Program Files
-Adobe
-Microsoft
-Folder X
-Drive D
-Folder Y
-Folder Z
In this one, everything derives from a root element (My PC).
In my case, a child could have more than 1 parent, like the following:
G A
\ /
B
/ \
X C
/ \
D E
\ /
F
So I have the following code:
create table #ObjectRelations
(
Id varchar(20),
NextId varchar(20)
)
insert into #ObjectRelations values ('G', 'B')
insert into #ObjectRelations values ('A', 'B')
insert into #ObjectRelations values ('B', 'C')
insert into #ObjectRelations values ('B', 'X')
insert into #ObjectRelations values ('C', 'E')
insert into #ObjectRelations values ('C', 'D')
insert into #ObjectRelations values ('E', 'F')
insert into #ObjectRelations values ('D', 'F')
declare @id varchar(20)
set @id = 'A';
WITH Objects (Id, NextId) AS
( -- This is the 'Anchor' or starting point of the recursive query
SELECT rel.Id,
rel.NextId
FROM #ObjectRelations rel
WHERE rel.Id = @id
UNION ALL -- This is the recursive portion of the query
SELECT rel.Id,
rel.NextId
FROM #ObjectRelations rel
INNER JOIN Objects -- Note the reference to CTE table name (Recursive Join)
ON rel.Id = Objects.NextId
)
SELECT o.*
FROM Objects o
drop table #ObjectRelations
Which returns the following SET:
Id NextId
-------------------- --------------------
A B
B C
B X
C E
C D
D F
E F
Expected result SET:
Id NextId
-------------------- --------------------
G B
A B
B C
B X
C E
C D
D F
E F
Note that the relation G->B is missing, because it asks for an starting object (which doesn't work for me also, because I don't know the root object from the start) and using A as the start point will ignore the G->B relationship.
So, this code doesn't work in my case because it asks for a starting object, which is obvious in a SINGLE-parent tree (will always be the root object). But in multi-parent tree, you could have more than 1 "root" object (like in the example, G and A are the "root" objects, where root is an object which doesn't have a parent (ancestor)).
So I'm kind of stucked in here... I need to modify the query to NOT ask for a starting object and recursively traverse the entire tree.
I don't know if that's possible with the (Id, NextId) implementation... may be I need to store it like a graph using some kind of Incidence matrix, adjacency matrix or whatever (see http://willets.org/sqlgraphs.html).
Any help? What do you think guys?
Thank you very much for your time =)
Cheers!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,我最终想出了以下解决方案。
这是我发现支持多根树和循环有向图的方式。
可能对某人有用。 这是给我的=P
谢谢
Well, I finally came up with the following solution.
It's the way I found to support multi-root trees and also cycling digraphs.
Could be useful for somebody. It is for me =P
Thanks
如果要使用所有根对象作为起始对象,则应首先更新数据以包含有关根对象(和叶子)的信息。 您应该添加以下插入:
当然,您也可以以这样的方式编写锚查询:选择具有不作为
NextId< 出现的
Id
的记录作为根节点。 /code>,但这更容易。接下来,将锚点查询修改为如下所示:
如果运行此查询,您会发现有很多重复项,很多弧出现多次。 这是因为您现在从锚点查询中获得了两个结果,因此树被遍历了两次。
可以通过将 select 语句更改为以下内容来解决此问题(请注意
DISTINCT
):If you want to use all root objects as starting objects, you should first update your data to include information about the root objects (and the leaves). You should add the following inserts:
Of course you could also write your anchor query in such a way that you select as root nodes the records that have an
Id
that does not occur as aNextId
, but this is easier.Next, modify your anchor query to look like this:
If you run this query, you'll see that you get a lot of duplicates, a lot of arcs occur multiple times. This is because you now have two results from your anchor query and therefore the tree is traversed two times.
This can be fixed by changing your select statement to this (note the
DISTINCT
):如果你不想做罗纳德建议的插入,这样做就可以了!
If you dont want to do the inserts suggested by Ronald,this would do!.