Build Enumeration Path from Adjacency List in SQL

假如想象 提交于 2021-01-28 05:27:22

问题


Initial scenario

My software uses a tree data structure, and I store it in SQL. I use the abstraction called Adjacency List which consists of each row storing ID and ParentID.

ID is Primary Key and ParentID is a Foreign Key to the same table.

The problem

I want to "convert" my SQL abstraction to Path Enumeration. It consists of each row storing ID and a varchar field storing the path of the IDs, from the root to the current row. For example, the Path field of the row with ID = 6 in this tree:

Tree

Would be /1/2/4/6/. More details here, by the name Lineage Column.

Question

How do I build a column Path from an existing database that only has ID and ParentID?


回答1:


SQL Server 2005 onwards should support the following:

WITH
  recursed_tree AS
(
  SELECT
    IDObject,
    concat('/', cast(IDObject as varchar(100)))   AS Path
  FROM
    tbObject
  WHERE
    ParentID IS NULL

  UNION ALL

  SELECT
    next.IDObject,
    concat(prev.Path, '/', cast(next.IDObject as varchar(100)))   AS Path
  FROM
    recursed_tree   AS prev
  INNER JOIN
    tbObject        AS next
       ON prev.IDObject = next.ParentID
)

SELECT
  *
FROM
  recursed_tree



回答2:


I came up with this SQL Server query:

[ tbObjectHierarchy has a FK and PK called IDObject and a varchar called Path ]

declare @T  as table (IDObject int, Path varchar(500))
declare @T2 as table (IDObject int, Path varchar(500))

insert into tbObjectHierarchy(IDObject, Path)
select o.IDObject, concat('/', cast(o.IDObject as varchar(100)), '/') as Path
from tbObject as o 
where o.ParentID is null

insert into @T (IDObject, Path)
select o.IDObject, concat(h.Path, cast(o.IDObject as varchar(100)), '/') as Path
from tbObject as o
inner join tbObjectHierarchy as h
on o.ParentID = h.IDObject

while exists (select top 1 * from @T)
begin
    insert into tbObjectHierarchy (IDObject, Path)
    select t.IDObject, t.Path
    from @T as t

    delete from @T2

    insert into @T2
    select o.IDObject, concat(t.Path, cast(o.IDObject as varchar(100)), '/') as Path
    from tbObject as o
    inner join @T as t
    on o.ParentID = t.IDObject

    delete from @T

    insert into @T
    select * from @T2
end


来源:https://stackoverflow.com/questions/23368657/build-enumeration-path-from-adjacency-list-in-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!