如何从分层 table 中在一行(行)中显示所有 parents ID

How to display all parents IDs in one line (row) from hierarchical table

我有一个层次结构 table,其中每个 child 都定义了一个 parent id(顶级 child 除外,其中 parent id 是无效的)。现在我想在一行中显示每个 parent id for selected child.

我试图使用 CTE,但 CTE 正在向初始集添加额外的记录。相反,我想用 parents.

列表更新初始集(SELECT 语句 selecting 一些 children)

table 的示例(表 1):

ChildID   ParentID
A         P
P         Q
Q         Z
B         P
C         F
F         M
M         Q
D         H
H         Y
Y         NULL
Z         NULL

如果初始语句将从 children ID 列表中 select C、A、Q,则预期结果如下:

Selected Child    Parent IDs
C                 F, M, Q, Z
A                 P, Q, Z
Q                 Z    

你用 CTE 做这个是对的,但是你必须把所有的行放在一列中(参见交叉应用 - xml 路径)。

with cte (selected, child, parent) as 
(  
  select s.id, t.*
  from @t as t
  inner join @selected as s on t.childid = s.id

  union all

  select cte.selected, t.*
  from @t as t
  inner join cte on t.childid = cte.parent
  where cte.parent is not null
)

select distinct
  t.selected as [Selected Child], 
  left(a.parents,len(a.parents) - 1) as Parents
from  cte t
  cross apply (select  cast(parent + ',' as text)
           from cte tt
           where t.selected = tt.selected
           for xml path('')) a(parents);

带有示例数据:

declare @t as table
( 
  childid char(1),
  parentid char(1)
);

declare @selected as table
(
  id char(1)
);


insert into @t (childid,parentid) values ('a','p'),
           ('p','q'),
           ('q','z'),
           ('b','p'),
           ('c','f'),
           ('f','m'),
           ('m','q'),
           ('d','h'),
           ('h','y'),
           ('y',null),
           ('z',null);

insert into @selected (id) values ('c'),('a'),('q');

with cte (selected, child, parent) as 
(  
  select s.id, t.*
  from @t as t
  inner join @selected as s on t.childid = s.id

  union all

  select cte.selected, t.*
  from @t as t
  inner join cte on t.childid = cte.parent
  where cte.parent is not null
)

select distinct
  t.selected as [Selected Child], 
  left(a.parents,len(a.parents) - 1) as Parents
from  cte t
  cross apply (select  cast(parent + ',' as text)
           from cte tt
           where t.selected = tt.selected
           for xml path('')) a(parents);