CTE递归查询以Child为参数获取Child Ancestors(自下而上)

时间:2017-04-20 13:35:21

标签: sql-server recursion stored-procedures common-table-expression hierarchical-data

我有一个层次表。我想要做的是检索基于 AgentID 的表层次结构作为参数。所以返回结果应该是降序。我在网上找到的大多数示例都显示了如何根据父作为参数检索层次结构表。

以下是我可以用来检索 Child / Parent / Parent ....层次结构的最接近的样本。 但是,如何使用AgentID作为参数来获得自下而上的层次结构?

    ;WITH rCTE AS 
     (
        SELECT  AgentID ,
        RootID ,
        CAST(AgentID AS NVARCHAR(MAX)) AS PathIDs,
        CAST(AgentName AS NVARCHAR(MAX)) AS PathText,
        CAST(IntroducerID AS NVARCHAR(MAX))  AS PathCost
FROM TblHierarchy r WHERE NOT EXISTS (SELECT * FROM TblHierarchy n WHERE r.AgentID = n.RootID ) 
UNION ALL
SELECT  n.AgentID ,
        n.RootID ,
        r.PathIDs  + '>' + CAST(n.AgentID AS NVARCHAR(10)) AS PathIDs,
        r.PathText + '>' + n.AgentName AS PathText,
        r.PathCost  + CAST(n.IntroducerID AS NVARCHAR(MAX)) AS PathCost
FROM rCTE r
INNER JOIN dbo.TblHierarchy n ON r.RootID = n.AgentID 



   )
    SELECT  PathIDs ,
            PathText ,
            PathCost     
             FROM rCTE r
      WHERE r.RootID =0--IS NULL 
      ORDER BY PathCost

   option (maxrecursion 0)

表格样本;

      CREATE TABLE [dbo].[TblHierarchy](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [AgentID] [int] NULL,
    [AgentName] [varchar](50) NULL,
    [RootID] [int] NULL,
    [IntroducerID] [int] NULL,
    [Description] [varchar](50) NULL
        ) ON [PRIMARY]

数据样本:

     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (1, 1, N'Toh', 0, 0, N'', NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (2, 2, N'Man', 1, 1, N'Child of Toh', NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (3, 3, N'Rul', 1, 1, N'Child of Toh', NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (4, 4, N'Rafiq', 2, 2, N'Child of Man', NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (5, 5, N'Paan', 2, 2, N'Child of Man', NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (7857, 6, N'TohChild0', 3, 1, NULL, NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (7858, 7, N'TohChild1', 3, 1, NULL, NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (7859, 8, N'TohChild2', 4, 1, NULL, NULL)
     INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree]) VALUES (7860, 9, N'TohChild3', 4, 1, NULL, NULL)

这是此CTE查询的当前结果

    255>127>63>31>15>7>3>1
    254>127>63>31>15>7>3>1
    253>126>63>31>15>7>3>1

结果就像我想要的那样,但这个太通用了。如何使用 AgentID 作为参数来获得此类结果。因此,结果只会返回一行。

修改

RootID是Parent,AgentID是Child ..我想获得自下而上的层次结构,意味着特定AgentID的所有父级

假设 AgentID = 327 因此,我的预期结果将是 327> 163> 81> 40> 20> 10> 5> 2> 1

提前致谢!

1 个答案:

答案 0 :(得分:0)

递归CTE有两部分:

  1. 递归种子。这是联合上面的第一个查询,您可以在其中设置迭代的起点。您的起点是选择不是agentid
  2. 的任何rootid
  3. 递归术语。这是一遍又一遍地调用的查询,直到连接条件失败,表示该特定分支的递归结束。
  4. 由于您希望仅获取特定agentid的结果,而不是 - agentid,而不是rootid - 就像您目前拥有的那样,然后更改{{1}关于递归种子的子句:

    WHERE

    作为第二个选项,您还可以将从递归CTE中选择的SELECT语句更改为WITH rCTE AS ( SELECT AgentID, RootID, CAST(AgentID AS NVARCHAR(MAX)) AS PathIDs, CAST(AgentName AS NVARCHAR(MAX)) AS PathText, CAST(IntroducerID AS NVARCHAR(MAX)) AS PathCost FROM TblHierarchy r WHERE AgentID = 327 UNION ALL SELECT n.AgentID, n.RootID, r.PathIDs + '>' + CAST(n.AgentID AS NVARCHAR(10)) AS PathIDs, r.PathText + '>' + n.AgentName AS PathText, r.PathCost + CAST(n.IntroducerID AS NVARCHAR(MAX)) AS PathCost FROM rCTE r INNER JOIN dbo.TblHierarchy n ON r.RootID = n.AgentID ) SELECT PathIDs, PathText, PathCost FROM rCTE r WHERE r.RootID = 0 --IS NULL