Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在父子关系中使用hierarchyId_Sql_Sql Server - Fatal编程技术网

Sql 在父子关系中使用hierarchyId

Sql 在父子关系中使用hierarchyId,sql,sql-server,Sql,Sql Server,我有一个名为tb\u Section的表。它旨在支持n级层次结构。在父/子关系的情况下,每一行都有一个指向另一行的节ID的ParentSetionId 现在,我有一个过程,我必须将这些部分一个一个地复制到另一个表中,保持层次结构不变。我使用order by对该部分进行了如下安排: Select s.SectionId, s.ParentSectionId, s.SectionName From tb_Section s Where s.TemplateId = 123 Order

我有一个名为tb\u Section的表。它旨在支持n级层次结构。在父/子关系的情况下,每一行都有一个指向另一行的节ID的ParentSetionId

现在,我有一个过程,我必须将这些部分一个一个地复制到另一个表中,保持层次结构不变。我使用order by对该部分进行了如下安排:

Select 
 s.SectionId,
 s.ParentSectionId,
 s.SectionName
From 
 tb_Section s
Where
 s.TemplateId = 123
Order By
 Convert(hierarchyid, '/' + cast(sec.ParentSectionId as varchar)+ '/')
Super-Parent
      Parent1
          Child1
          Child2
      Parent2
          Child3
          Child4
我将这些插入一个表中,并将每个部分逐个插入另一个表中。这很好用。但在应用程序上线后,出现了一个问题

用户首先创建所有节作为父节,然后逐个编辑它们并使其成为其他节的子节(使用最困难的方式:/),节层次结构如下:

Select 
 s.SectionId,
 s.ParentSectionId,
 s.SectionName
From 
 tb_Section s
Where
 s.TemplateId = 123
Order By
 Convert(hierarchyid, '/' + cast(sec.ParentSectionId as varchar)+ '/')
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 |
+-----------+-----------------+---------------+--------------+----------------+

您可以看到层次结构不同,在这里,子项显示在父项之前。我希望此示例数据有帮助。

尝试使用递归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

尝试使用递归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

从您提供的数据来看,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
“Child N”值的值看起来不显示返回超级父级的任何连接。因此,让我们运行以下更新:

UPDATE  [dbo].[tb_Section]
SET     [h] = CONCAT('/686778', h.ToString())
WHERE   [SectionName] LIKE 'Child%'
我们正在变得更好,但是现在如果我们再次运行上一步中的select,结果将基于层次深度返回。也就是说,超级父母首先回来,然后是父母,最后是孩子。当您查看层次结构的字符串值时,这仍然是有意义的;所有父行都具有相同的层次结构值,因此它们将一起排序

最后一次更新应该会让您到达您想要去的地方:

UPDATE  [dbo].[tb_Section]
SET     [h] = CONCAT(ISNULL(h.ToString(), '/'), [SectionId], '/')

现在,当您再次运行相同的选择时,子层次结构将被排序在一起。因此,TL;这个问题的关键在于,HierarchyID需要提供从源(在您的情况下为超级父级)到目标(在您的情况下为子级)的完整路径。根据您提供的数据,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
“Child N”值的值看起来不显示返回超级父级的任何连接。因此,让我们运行以下更新:

UPDATE  [dbo].[tb_Section]
SET     [h] = CONCAT('/686778', h.ToString())
WHERE   [SectionName] LIKE 'Child%'
我们正在变得更好,但是现在如果我们再次运行上一步中的select,结果将基于层次深度返回。也就是说,超级父母首先回来,然后是父母,最后是孩子。当您查看层次结构的字符串值时,这仍然是有意义的;所有父行都具有相同的层次结构值,因此它们将一起排序

最后一次更新应该会让您到达您想要去的地方:

UPDATE  [dbo].[tb_Section]
SET     [h] = CONCAT(ISNULL(h.ToString(), '/'), [SectionId], '/')

现在,当您再次运行相同的选择时,子层次结构将被排序在一起。因此,TL;这一点的关键在于,HierarchyID需要提供从源(在您的情况下为超级父级)到目标(在您的情况下为子级)的完整路径。

这里是一个很好的起点。一个原始表数据的示例很有用为什么不使用hierachyid类型@SteveFord的可能重复项我在order by语句中使用了hierarchyId,但是hierarchyId只有在数据插入树状表单时才能正常工作。在这里,叶节点首先作为父节点添加,然后更改为叶节点。一个原始表数据的示例很有用为什么不使用hierachyid类型@SteveFord的可能重复项我在order by语句中使用了hierarchyId,但是hierarchyId只有在数据插入树状表单时才能正常工作。在这里,叶节点首先作为父节点添加,然后更改为叶节点。谢谢。这个很好用。但就大数据而言,CTE不是很慢吗?@ZunairZubair对于大型查询来说可能很慢,如果你知道只有3个级别,那么你可以通过连接和UNIONSI的n级层次结构来实现同样的效果。但目前它工作正常。谢谢。这个很好用。但就大数据而言,CTE不是很慢吗?@ZunairZubair对于大型查询来说可能很慢,如果你知道只有3个级别,那么你可以通过连接和UNIONSI的n级层次结构来实现同样的效果。但它目前运行良好。