2

我有一个表,其中包含对象的标识符和其父母的标识符。它用于保存以树的形式呈现的数据对象。我想查询表以构建树中对象的完整路径。树的最大深度可能永远不会超过 20 个对象。有没有办法在没有while循环的情况下做到这一点......或者是否值得尝试避免这种类型/大小的工作的while循环。

该表如下所示:

创建表 [dbo].[tblObj]
(
    [ObjectId] [int] 非空,
    [对象名] [nvarchar](50) 非空,
    [ParentId] [int] NULL,
)

有这样的数据

插入 tblObj (ObjectId, ObjectName) 值 (1, 'Root')
插入 tblObj (ObjectId, ObjectName, ParentId) 值 (2, 'Middle1', 1)
插入 tblObj (ObjectId, ObjectName, ParentId) 值 (3, 'Middle2', 2)
插入 tblObj (ObjectId, ObjectName, ParentId) 值 (4, 'Leaf', 3)

期望的结果是使用对象/父关系来构建一个包含反映完整路径的对象名称的字符串。上面的数据将导致路径“Root\Middle1\Middle2\Leaf”

4

2 回答 2

2

递归 CTE 非常常用于此类任务。下面的查询将给出 (ObjectId, Path) 对中所有行的列表dbo.tblObj

;WITH cte (ObjectId, ParentID, [ObjectName], Path)
AS(
    SELECT [ObjectId], [ParentID], [ObjectName], cast([ObjectName] as nvarchar(max))
    FROM dbo.tblObj
    WHERE [ParentID] is NULL
    UNION ALL
    SELECT t.[ObjectId], t.ParentID, t.[ObjectName], cte.Path + '\' + t.[ObjectName]
    FROM cte
        JOIN dbo.tblObj t ON t.ParentID = cte.[ObjectId]
)
select ObjectID, Path
from cte

如果您需要获取特定对象的路径,您可以这样做:

declare @objId int
set @objId = 4

;WITH cte (ObjectId, ParentID, [ObjectName], Path)
AS(
    -- here code is the same as above
)
select Path
from cte
where ObjectID = @objId

或者,或者,作为:

declare @objId int
set @objId = 4

;with PathSteps(ObjectId, ParentID, ObjectName, Level)
as
(
    select ObjectId, ParentID, ObjectName, 0
    from dbo.tblObj
    where ID = @id
    union all
    select t.ObjectId, t.ParentID, t.ObjectName, p.Level - 1
    from dbo.tblObj t
        join PathSteps p on p.ParentID = t.ID
),
Path(ObjectPath) as (
    select stuff(
        (select '\' + ObjectName
        from PathSteps
        order by Level
        for xml path(''), type).value('text()[1]', 'nvarchar(max)'), 1, 1, '')
)
select ObjectPath
from Path
于 2013-08-26T17:42:51.083 回答
0

实现结果的一种简单方法是使用:

DECLARE @var VARCHAR(MAX) = ''
SELECT @var = CASE WHEN @var = '' THEN '' ELSE @var+'/' END + ObjectName 
FROM tblObj ORDER BY ObjectId
PRINT @var
于 2016-09-07T07:46:06.670 回答