列出层次结构表中项目的所有父项作为分隔字符串SQL

时间:2017-05-26 09:23:33

标签: sql sql-server-2012

我有一个像这样的SQL表

ID        Name        ParentID
------------------------------
1        Alex          0
2        John          0
3        Don           1
4        Philip        2
5        Shiva         2
6        San           3
7        Antony        6
8        Mathew        2
9        Cyril         8
10       Johan         9
-------------------------

我正在寻找像这样的外线

如果我传递ID 7,10

输出表将是

ID          Name           Relation
------------------------------------
7           Antony         Alex->Don->San->Antony
10          Johan          John->Mathew->Cyril->Johan

如何使用CTE

实现这一目标

2 个答案:

答案 0 :(得分:4)

这似乎可以解决问题。关键是要意识到我们可以向后建立路径并在我们不再有父母找到时停止:

DECLARE @t table (ID int not null, Name varchar(19) not null, ParentID int null)
insert into @t(ID,Name,ParentID) values
(1 ,'Alex',null),
(2 ,'John',null),
(3 ,'Don',1),
(4 ,'Philip',2),
(5 ,'Shiva',2),
(6 ,'San',3),
(7 ,'Antony',6),
(8 ,'Mathew',2),
(9 ,'Cyril',8),
(10,'Johan',9)

declare @search table (ID int not null)
insert into @search (ID) values (7),(10)

;With Paths as (
    select s.ID as RootID,t.ID,t.ParentID,t.Name, CONVERT(varchar(max),t.Name) as Path
    from
        @search s
            inner join
        @t t
            on
                s.ID = t.ID
    union all
    select p.RootID,t.ID,t.ParentID,p.Name, t.Name + '->' + p.Path
    from Paths p
            inner join
        @t t
            on
                p.ParentID = t.ID
)
select * from Paths where ParentID is null

结果:

RootID      ID          ParentID    Name                Path
----------- ----------- ----------- ------------------- ----------------------------
10          2           NULL        Johan               John->Mathew->Cyril->Johan
7           1           NULL        Antony              Alex->Don->San->Antony

(我已经在其他专栏中留下来帮助显示最终状态。在没有过滤的情况下查询CTE也可能具有指导意义)

我还提醒说,如果可能的话,我通常不会使用分隔字符串 - 当SQL Server的设计类型时,它不是很好的表示使用多个值。

答案 1 :(得分:1)

使用公用表表达式查询:

 CREATE TABLE #Table(ID  INT,Name VARCHAR(MAX),ParentID INT)

 INSERT INTO #Table(ID  ,Name ,ParentID)
 SELECT 1,'Alex',0 UNION ALL    
 SELECT 2,'John',0 UNION ALL    
 SELECT 3,'Don',1 UNION ALL 
 SELECT 4,'Philip',2 UNION ALL  
 SELECT 5,'Shiva',2 UNION ALL   
 SELECT 6,'San',3 UNION ALL  
 SELECT 7,'Antony',6 UNION ALL  
 SELECT 8,'Mathew',2 UNION ALL  
 SELECT 9,'Cyril',8 UNION ALL   
 SELECT 10,'Johan',9

 ;WITH Relationship ( _ID , _Name , _Relation , _ParentId)  AS
 (
   SELECT ID  , Name , Name , ID
   FROM #Table
   WHERE ParentID = 0
   UNION ALL
   SELECT ID , Name , _Relation + '->' + Name , _ParentId
   FROM Relationship
   JOIN #Table ON _ID = ParentID
 )

 SELECT _ID ID, _Name Name, _Relation Relation 
 FROM Relationship
 WHERE _ID IN ( SELECT MAX(_ID) FROM Relationship GROUP BY _ParentId)