2

我在 SQL Server 2014 中工作。我有一个奇怪的数据层次结构情况。(至少,我以前没有经历过类似的事情。)

在我的层次结构中,有几个根/最高级别的对象。根级别以下的每个对象都映射到它上面的一个且只有一个对象。并非每个节点路径的长度都相同。例如,一条路径中可能有 2 个对象级别,而另一条路径中可能有 20 个对象级别。

层次结构中的每个对象都有一个IsInherited属性,以及一些其他属性(称为它SomeAttribute)。该属性指示给定对象是否从其最直接IsInherited的父对象继承 的值。SomeAttribute自然地,如果一个对象的IsInherited属性是'Y',那么,给定的对象SomeAttribute从其最直接的父级继承值(反过来,它可以继承其最直接的父级的值,等等)。否则,指定对象的SomeAttribute值。

现在,以上所有情况都不一定不常见。使这种情况不常见的是这种继承的特定实现。此层次结构存储在单个表中(这是否使其成为邻接列表模型?),如果其属性为“Y” ,SomeAttribute不会为给定对象/行填充的值。IsInherited

我的目标是返回SomeAttribute层次结构中所有对象的值。

表格示例如下:

CREATE TABLE hierarchy (
    ID int NOT NULL
    ,ParentID int NULL
    ,SomeAttribute char(1) NULL
    ,IsInherited char(1) NOT NULL
)
;
INSERT INTO hierarchy (ID, ParentID, SomeAttribute, IsInherited)
VALUES
(1, NULL, 'a', 'N')
,(2, NULL, 'b', 'N')
,(3, NULL, 'c', 'N')
,(4, NULL, 'd', 'N')
,(5, NULL, 'e', 'N')
,(6, NULL, 'f', 'N')
,(7, NULL, 'g', 'N')
,(8, 2, NULL, 'Y')
,(9, 3, 'h', 'N')
,(10, 4, NULL, 'Y')
,(11, 5, 'j', 'N')
,(12, 6, NULL, 'Y')
,(13, 6, 'k', 'N')
,(14, 7, 'l', 'N')
,(15, 7, 'm', 'N')
,(16, 10, NULL, 'Y')
,(17, 11, NULL, 'Y')
,(18, 16, NULL, 'Y')
,(19, 17, NULL, 'Y')
,(20, 19, 'o', 'N')
;

这为我们提供了以下节点路径:

1
2-8
3-9
4-10-16-18
5-11-17-19-20
6-12,13
7-14,15

因此,使用此示例表,我希望返回:

ID    SomeAttribute
1     a
2     b
3     c
4     d
5     e
6     f
7     g
8     b (inherited from 2)
9     h
10    d (inherited from 4)
11    j
12    f (inherited from 6)
13    k
14    l
15    m
16    d (inherited from 10, inherited from 4)
17    j (inherited from 11)
18    d (inherited from 16, inherited from 10, inherited from 4)
19    j (inherited from 17, inherited from 11)
20    o

我知道这可能需要递归 CTE。我正在努力为此编写 SQL。如何返回我想要的输出?

4

1 回答 1

4

这是邻接表模型,因为每一行代表一对相邻节点。

递归 CTE 如下所示:

 with q as
(
  select id, SomeAttribute, cast(id as varchar(max)) SomeAttributePath
  from hierarchy
  where ParentID is null
  union all
  select c.id, case when c.IsInherited = 'Y' then q.SomeAttribute else c.SomeAttribute end as SomeAttribute, cast(concat(q.SomeAttributePath,'-',c.id) as varchar(max))
  from q
  join hierarchy c
  on c.ParentID = q.ID
)
select *
from q
order by id

输出:

id          SomeAttribute SomeAttributePath
----------- ------------- -----------------
1           a             1
2           b             2
3           c             3
4           d             4
5           e             5
6           f             6
7           g             7
8           b             2-8
9           h             3-9
10          d             4-10
11          j             5-11
12          f             6-12
13          k             6-13
14          l             7-14
15          m             7-15
16          d             4-10-16
17          j             5-11-17
18          d             4-10-16-18
19          j             5-11-17-19
20          o             5-11-17-19-20
于 2017-06-23T20:20:27.173 回答