我在SQL Server 2012中具有下面的表结构
INSERT INTO tblLocations (Relation, ParentID, Name, Levelnumber, Code)
VALUES
('Parent', NULL, 'West',0,'X'),
('Child', 1, 'WA',1,'X'),
('Grandchild', 2, 'Seattle',2,'X'),
('Grandchild', 2, 'Seattle2',2,'X'),
('GreatGrandchild', 3, 'aa',3,'X'),
('GreatGrandchild', 3, 'bb',3,'X'),
('Parent', NULL, 'MidWest',0,'Y'),
('Child', 7, 'IL',1,'Y'),
('Grandchild', 8, 'Chicago',2,'Y'),
('Grandchild',8, 'Chicago1',2,'Y'),
('GreatGrandchild', 9, 'cc',3,'Y'),
('GreatGrandchild', 9, 'dd',3,'Y'),
('Parent', NULL, 'South',0,'Z'),
('Child', 13, 'TX',1,'Z'),
('GreatGrandchild', 14, 'ff',3,'Z'),
('GreatGrandchild', 14, 'ff',3,'Z'),
('Parent', NULL, 'North',0,'A'),
('Grandchild',17, 'Chicago1',2,'A'),
('GreatGrandchild', 18, 'ff',3,'A'),
('GreatGrandchild', 18, 'ff',3,'A');
我们可以看到某些级别对于所有节点都不存在。我们的要求是获取所有节点的所有级别。
例如,对于代码X
Parent -> Child -> GrandChild --> GreatGrandchild
层次结构存在..但是对于代码A,我们有
Parent -> GrandChild -> GreatGrandChild
类似于代码Z:
Parent -> Child -> GreatGrandChild
我们的要求是,如果不存在一个级别,则应为缺少的级别填充下一个级别(由级别编号标识)。我们只有4个级别。.
我们总是需要
Parent -> Child (if child is not there search down (Grandchild / GreatGrandchild) until data is there and populate as Child)
-> GrandChild - > GreatGrandChild
这是我们获得的CTE,
WITH Hierarchy AS
(
-- initialization
SELECT Relation, ParentID, Name, Levelnumber, Code
FROM tblLocations
WHERE LevelNumber = 0
UNION ALL
-- recursive execution
SELECT S.Relation, S.ParentID,S.Name,S.Levelnumber, S.Code
FROM tblLocations S
INNER JOIN tblLocations T ON T.Id = S.ParentId
)
SELECT *
FROM Hierarchy
WHERE Code = 'X' ;
在视图中需要它,因此不需要T-SQL。
友好的指导
答案 0 :(得分:0)
您的递归查询存在问题,因为它不是递归的。根据定义,递归查询是自引用的。您编写查询的方式,应定义递归的部分只是表与其自身的常规连接。
也就是说,一切并没有丢失。这是我想出的:
WITH Hierarchy AS
(
--initialization
SELECT ID,
Relation,
ParentID, [Name],
Levelnumber,
Code,
1 AS [__level__],
cast(concat('/', ID, '/') as varchar(max)) as h
FROM tblLocations
WHERE LevelNumber = 0
UNION ALL
--recursive execution
SELECT child.ID,
child.Relation,
child.ParentID,
child.Name,
child.Levelnumber,
child.Code,
parent.[__level__] + 1,
cast(concat(parent.h, child.ID, '/') as varchar(max)) as h
FROM tblLocations child
INNER JOIN Hierarchy AS parent
ON parent.Id = child.ParentId
)
SELECT *,
choose(
Hierarchy.[__level__],
'Parent',
'Child',
'GrandChild',
'GreatGrandchild'
) as [DerivedRelation]
FROM Hierarchy
WHERE Code = 'A'
order by h;
实际的递归查询是相当标准的层次结构遍历。为了满足您的要求,我正在计算自己在层次结构中所处位置的概念,以便可以使用它来确定要显示为关系的内容。您没有说您正在使用什么版本的SQL,因此您可能没有concat()
和choose()
。没关系;它们只是string + string
和case
语句周围的语法糖。
我在这里还要注意的另一件事是h
列。我已经写了相当一部分分层查询,对于它们的实际运行时执行,我更喜欢hierarchyid。您在维护数据上花了一点钱,但是与它们一起进行查询是相当有效的(因为您可以索引层次结构并说诸如where h.IsDescendentOf(some_other_hierarchyID)
之类的东西。所有这些就是说h
如果您想朝该方向前进,则该列可以直接转换为architectureid。