我有一个名为 tb_Section 的表格。它旨在支持n级层次结构。每行都有一个 ParentSetionId ,如果是父/子关系,则指向另一行 SectionId 。
现在,我有一个过程,我必须将这些部分逐个复制到另一个表,保持层次结构不变。我按照以下顺序安排了部分:
Select
s.SectionId,
s.ParentSectionId,
s.SectionName
From
tb_Section s
Where
s.TemplateId = 123
Order By
Convert(hierarchyid, '/' + cast(sec.ParentSectionId as varchar)+ '/')
我将这些插入到TempTable中,并将每个部分逐个插入另一个表中。这工作正常。但在申请上线后,报道了一个问题。
用户首先将所有部分创建为父部分,然后逐个编辑它们并使其成为其他部分的子级(使用最困难的方式:/)部分层次结构如下:
Super-Parent
Parent1
Child1
Child2
Parent2
Child3
Child4
在这种情况下,上述查询按顺序返回以下行。
SuperParent
Child1
Child2
Parent1
Child3
Child4
Parent2
而不是正常情况,应该是这个
SuperParent
Parent1
Child1
Child2
Parent2
Child3
Child4
对此有何帮助?我似乎无法找到发生这种情况的原因。
更新
这是首先插入子项的SQL脚本。
CREATE TABLE tb_Section(
SectionId BIGINT NOT NULL PRIMARY KEY
,ParentSectionId BIGINT
,SectionName NVARCHAR(50) NOT NULL
);
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (SectionId,ParentSectionId,N'SectionName');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686772,686776,N'Child 1');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686773,686776,N'Child 2');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686774,686777,N'Child 3');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686775,686777,N'Child 4');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686776,686778,N'Parent 1');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686777,686778,N'Parent 2');
INSERT INTO tb_Section(SectionId,ParentSectionId,SectionName) VALUES (686778,NULL,N'Super-Parent');
以上是我的上述查询返回 hierarchyId
的结果+-----------+-----------------+---------------+--------------+----------------+
| SectionId | ParentSectionId | SectionTypeId | SectionName | hierarchy |
+-----------+-----------------+---------------+--------------+----------------+
| 686778 | NULL | 1 | Super-Parent | NULL |
| 686772 | 686776 | 2 | Child 1 | 0xF800298C6620 |
| 686773 | 686776 | 2 | Child 2 | 0xF800298C6620 |
| 686774 | 686777 | 2 | Child 3 | 0xF800298C6660 |
| 686775 | 686777 | 2 | Child 4 | 0xF800298C6660 |
| 686776 | 686778 | 2 | Parent 1 | 0xF800298C66A0 |
| 686777 | 686778 | 2 | Parent 2 | 0xF800298C66A0 |
+-----------+-----------------+---------------+--------------+----------------+
您可以看到层次结构不同,此处子项显示在“父项”之前。我希望这些样本数据有所帮助。
答案 0 :(得分:1)
尝试使用递归CTE并创建自己的层次结构字符串:
;WITH Recurs
AS
(
SELECT SectionId, ParentSectionId,
SectionName, '/' + CAST(SectionId AS VARCHAR(MAX)) as Level
FROM tb_Section
WHERE ParentSectionId Is NULL
UNION ALL
SELECT s.SectionId, s.ParentSectionId, s.SectionName,
CAST(r.level + '/' + CAST(s.SectionId AS VARCHAR(MAX) )AS Varchar(MAX))
FROM tb_Section s
INNER JOIN recurs r
ON S.ParentSectionId = r.SectionId
)
SELECT *
FROM Recurs
ORDER BY Level
产地:
SectionId ParentSectionId SectionName Level
686778 NULL Super-Parent /686778
686776 686778 Parent 1 /686778/686776
686772 686776 Child 1 /686778/686776/686772
686773 686776 Child 2 /686778/686776/686773
686777 686778 Parent 2 /686778/686777
686774 686777 Child 3 /686778/686777/686774
686775 686777 Child 4 /686778/686777/686775
答案 1 :(得分:1)
根据您提供的数据,HierarchyID值对我来说不正确。当我运行此查询时:
CREATE TABLE tb_Section(
SectionId BIGINT NOT NULL PRIMARY KEY
,ParentSectionId BIGINT
,SectionName NVARCHAR(50) NOT NULL
, h HIERARCHYID
);
INSERT INTO [tb_Section]
( [SectionId], [ParentSectionId], [SectionName], [h] )
VALUES ( 686778, NULL, 'Super-Parent', NULL ),
( 686772, 686776, 'Child 1', 0xF800298C6620 ),
( 686773, 686776, 'Child 2', 0xF800298C6620 ),
( 686774, 686777, 'Child 3', 0xF800298C6660 ),
( 686775, 686777, 'Child 4 ', 0xF800298C6660 ),
( 686776, 686778, 'Parent 1 ', 0xF800298C66A0 ),
( 686777, 686778, 'Parent 2 ', 0xF800298C66A0 );
SELECT [ts].[SectionId] ,
[ts].[ParentSectionId] ,
[ts].[SectionName] ,
[ts].[h].ToString()
FROM [dbo].[tb_Section] AS [ts]
ORDER BY h
“子N”值的值看起来没有显示任何与超级父级的连接。所以让我们运行以下更新:
UPDATE [dbo].[tb_Section]
SET [h] = CONCAT('/686778', h.ToString())
WHERE [SectionName] LIKE 'Child%'
我们正在变得更好,但现在如果我们再次运行上一步中的选择,结果将根据层次结构深度返回。也就是说,超级父母首先回来,然后是父母,然后是最后的孩子。其中,当你看到层次结构的字符串值仍然有意义;所有父行都具有相同的层次结构值,因此它们将一起排序。
最后一次更新应该可以让您到达目的地:
UPDATE [dbo].[tb_Section]
SET [h] = CONCAT(ISNULL(h.ToString(), '/'), [SectionId], '/')
现在,当您再次运行相同的选择时,子层次结构将一起排序。所以TL; DR就是这个,HierarchyID需要提供从源(在你的情况下,Super-Parent)到目的地(在你的情况下,Child)的完整路径,包括在内。