2016-03-15 35 views
0

我有一个名为tb_Section的表。它旨在支持n级层次结构。每行有一个ParentSetionId指向另一行的SectionId在父/子关系的情况下。在父项中使用hierarchyId子项关系

现在,我有一个过程,我必须将这些节逐一复制到另一个表中,保持层次结构完整。我通过如下使用顺序排列的部分:

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 

对此任何帮助吗?我似乎无法找到发生这种情况的原因。

UPDATE

下面是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 | 
+-----------+-----------------+---------------+--------------+----------------+ 

你可以看到,层次不同的是,这里的孩子资料的家长表示前面。我希望这个样本数据有帮助。

+1

这是一个很好的开始。 http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ –

+1

原始表格数据的示例将很有用 –

+0

为什么不使用hierachid键入https://msdn.microsoft.com/en-us/library/bb677173.aspx –

回答

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 
+0

谢谢。这工作正常。但就大数据而言,CTE会不会变慢? –

+0

@ZunairZubair对于大型查询可能会很慢,如果您知道只有3个级别,那么您可以通过JOINS和UNIONS完成相同的操作 –

+0

我有n级别的层次结构。但目前它的工作很好。 –

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需要提供从源代码(在你的情况下,超级父代)到目的地(在你的情况下,子代)的完整路径,包括在内。