我有一个表,其中包含对象的标识符和父项的标识符。它用于保存呈现为树的数据对象。我想查询表以构建树中对象的完整路径。树的最大深度可能永远不会超过20个对象。有没有办法在没有while循环的情况下执行此操作...或者是否值得尝试避免此类型/大小工作的while循环。
表格如下:
CREATE TABLE [dbo].[tblObj] ( [ObjectId] [int] NOT NULL, [ObjectName] [nvarchar](50) NOT NULL, [ParentId] [int] NULL, )
使用这样的数据
insert into tblObj (ObjectId, ObjectName) values (1, 'Root') insert into tblObj (ObjectId, ObjectName, ParentId) values (2, 'Middle1', 1) insert into tblObj (ObjectId, ObjectName, ParentId) values (3, 'Middle2', 2) insert into tblObj (ObjectId, ObjectName, ParentId) values (4, 'Leaf', 3)
期望的结果是使用对象/父关系来构建具有反映完整路径的对象名称的字符串。上面的数据将导致路径“Root \ Middle1 \ Middle2 \ Leaf”
答案 0 :(得分:1)
递归CTE非常常用于此类任务。下面的查询将给出dbo.tblObj
中所有行的(ObjectId,Path)对列表:
;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
答案 1 :(得分:0)
实现结果的简单方法是使用:
DECLARE @var VARCHAR(MAX) = ''
SELECT @var = CASE WHEN @var = '' THEN '' ELSE @var+'/' END + ObjectName
FROM tblObj ORDER BY ObjectId
PRINT @var