sql中的拓扑排序

发布于 2024-10-26 06:50:31 字数 373 浏览 2 评论 0原文

我正在解决表中某些对象之间的依赖关系。 我必须对对象做一些事情来排序它们的依赖性。 例如,第一个对象不依赖于任何对象。第二个和第三个取决于第一个,依此类推。我必须使用拓扑排序。 有人可以展示在 t-sql 中进行排序的实现示例吗? 我有一张表:

create table dependency
(
  DependencyId PK
  ,ObjectId
  ,ObjectName
  ,DependsOnObjectId
)

我想获取

ObjectId 对象名 排序顺序

I am resolving dependency between some objects in a table.
I have to do something with objects in order their dependency.
For example, the first object doesn't depend on any object. The second and third ones depends on first one and so on. I have to use topological sorting.
Could someone show the sample of implementation so sorting in t-sql.
I have a table:

create table dependency
(
  DependencyId PK
  ,ObjectId
  ,ObjectName
  ,DependsOnObjectId
)

I want to get

ObjectId
ObjectName
SortOrder

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨后彩虹 2024-11-02 06:50:31

它接缝,它有效:

declare @step_no int

declare @dependency table 
(
  DependencyId  int
  ,ObjectId     int 
  ,ObjectName   varchar(100)
  ,DependsOnObjectId int 
  ,[rank]       int         NULL
  ,degree       int         NULL
);

insert into @dependency values (5, 5, 'Obj 5', 2, NULL, NULL)
insert into @dependency values (6, 6, 'Obj 6', 7, NULL, NULL)
insert into @dependency values (2, 2, 'Obj 2', 1, NULL, NULL)
insert into @dependency values (3, 3, 'Obj 3', 1, NULL, NULL)
insert into @dependency values (1, 1, 'Obj 1', 1, NULL, NULL)
insert into @dependency values (4, 4, 'Obj 4', 2, NULL, NULL)
insert into @dependency values (7, 7, 'Obj 7', 2, NULL, NULL)


update @dependency set rank = 0
-- computing the degree of the nodes
update  d set d.degree = 
    (
        select count(*) from @dependency t
        where t.DependsOnObjectId = d.ObjectId 
        and t.ObjectId <> t.DependsOnObjectId
    )
from @dependency d


set @step_no = 1
while 1 = 1
begin
    update @dependency set rank = @step_no where degree = 0

    if (@@rowcount = 0) break
    update @dependency set degree = NULL where rank = @step_no

    update d set degree = (
        select count(*) from @dependency t
        where t.DependsOnObjectId = d.ObjectId and t.ObjectId != t.DependsOnObjectId
        and t.ObjectId in (select tt.ObjectId from @dependency tt where tt.rank = 0))
    from @dependency d
    where d.degree is not null

    set @step_no = @step_no + 1
end

select * from @dependency order by rank

It seams, it works:

declare @step_no int

declare @dependency table 
(
  DependencyId  int
  ,ObjectId     int 
  ,ObjectName   varchar(100)
  ,DependsOnObjectId int 
  ,[rank]       int         NULL
  ,degree       int         NULL
);

insert into @dependency values (5, 5, 'Obj 5', 2, NULL, NULL)
insert into @dependency values (6, 6, 'Obj 6', 7, NULL, NULL)
insert into @dependency values (2, 2, 'Obj 2', 1, NULL, NULL)
insert into @dependency values (3, 3, 'Obj 3', 1, NULL, NULL)
insert into @dependency values (1, 1, 'Obj 1', 1, NULL, NULL)
insert into @dependency values (4, 4, 'Obj 4', 2, NULL, NULL)
insert into @dependency values (7, 7, 'Obj 7', 2, NULL, NULL)


update @dependency set rank = 0
-- computing the degree of the nodes
update  d set d.degree = 
    (
        select count(*) from @dependency t
        where t.DependsOnObjectId = d.ObjectId 
        and t.ObjectId <> t.DependsOnObjectId
    )
from @dependency d


set @step_no = 1
while 1 = 1
begin
    update @dependency set rank = @step_no where degree = 0

    if (@@rowcount = 0) break
    update @dependency set degree = NULL where rank = @step_no

    update d set degree = (
        select count(*) from @dependency t
        where t.DependsOnObjectId = d.ObjectId and t.ObjectId != t.DependsOnObjectId
        and t.ObjectId in (select tt.ObjectId from @dependency tt where tt.rank = 0))
    from @dependency d
    where d.degree is not null

    set @step_no = @step_no + 1
end

select * from @dependency order by rank
我们只是彼此的过ke 2024-11-02 06:50:31

您有一个简单的树结构,每个 ObjectId 只有一条路径,因此基于遍历的 DependsOnObjectId 链接数量的标签仅给出一个答案,并且是一个足够好的答案来处理正确的内容第一的。使用公用表表达式很容易做到这一点,并且具有易于移植的优点:

with dependency_levels as
(
  select ObjectId, ObjectName, 0 as links_traversed 
  from dependency where DependsOnObjectId is null
  union all
  select ObjectId, ObjectName, links_traversed+1
  from dependecy 
  join dependency_levels on dependency.DependsOnObjectId = dependency_levels.ObjectId
)
select ObjectId, ObjectName, links_traversed
from dependency_levels
order by links_traversed

You have a simple tree structure with only one path to each ObjectId so labeling based off number of DependsOnObjectId links traversed gives only one answer and a good enough answer to process the right stuff first. This is easy to do with a common table expression and has the benefit of easy portability:

with dependency_levels as
(
  select ObjectId, ObjectName, 0 as links_traversed 
  from dependency where DependsOnObjectId is null
  union all
  select ObjectId, ObjectName, links_traversed+1
  from dependecy 
  join dependency_levels on dependency.DependsOnObjectId = dependency_levels.ObjectId
)
select ObjectId, ObjectName, links_traversed
from dependency_levels
order by links_traversed
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文