SQL父子树数据仅返回列表

时间:2018-04-18 15:21:06

标签: sql-server recursion parent-child

我在SQL数据库中有一个父子树关系。有许多表保存我的所有数据/关系,我需要的重要数据在下表中,我使用递归CTE查询来获取它。我的应用程序和数据库设计非常适合我正在做的事情。我需要运行一些管理/维护来确认数据是否正确,我想要做的是概述如下:

我的数据集包含的内容是: - FilterID - 这是父记录ID - 深度 - 在我的CTE中,这给了我树关系的记录数。 - sortCol - 在我的CTE中我正在构建它(这只是所有FilterID的组合二进制字符串) - TreeListOfFilterIDs - 这是此级别此记录树中所有FilterID的列表。 - 我想要的结果 - 这是我添加的一列,用于标识我想从数据集中返回的字段列表

在此示例中,FilterID 35是起始记录。父子关系可以有1个父母和2个(更多)不同的孩子路径,因此1个父母可以有2个或更多个不同的孩子。注意:这种版权关系是故意的,因为1父母可以有2个不同的孩子,我在我的代码/流程中使用它。

从下面的数据集中我需要获得的是仅返回每个节点中父/子关系的最终路径的记录。我在下面的数据中添加了一个列,我的查询中没有“我想要的结果”,其中我只想获取带有“X”的记录。

我正在填充表格,我的代码/流程正在处理我如何设计所有内容。我现在尝试用这个逻辑来完成的是找到唯一的最终路径,这样我就可以轻松识别每个最终路径并确保它们是正确的。这将用于维护数据和路径的维护目的。

FilterID    depth   sortCol                                                 TreeListOfFilterIDs     RESULTS I WANT
35          0       0x00000023                                              35
36          1       0x0000002300000024                                      35,36
37          2       0x000000230000002400000025                              35,36,37
39          3       0x00000023000000240000002500000027                      35,36,37,39             X
38          2       0x000000230000002400000026                              35,36,38
40          3       0x00000023000000240000002600000028                      35,36,38,40
44          4       0x000000230000002400000026000000280000002C              35,36,38,40,44          X
41          3       0x00000023000000240000002600000029                      35,36,38,41
45          4       0x000000230000002400000026000000290000002D              35,36,38,41,45          X
42          3       0x0000002300000024000000260000002A                      35,36,38,42
46          4       0x0000002300000024000000260000002A0000002E              35,36,38,42,46          X
43          3       0x0000002300000024000000260000002B                      35,36,38,43
47          4       0x0000002300000024000000260000002B0000002F              35,36,38,43,47
48          5       0x0000002300000024000000260000002B0000002F00000030      35,36,38,43,47,48       X
49          5       0x0000002300000024000000260000002B0000002F00000031      35,36,38,43,47,49       X

注意,上述数据来自我的CTE结果,但是按sortcol值排序(因此这不是数据插入CTE的顺序)。

生成上述结果的SQL:

-- this combines the required answers for the next questions to display (will join to what is filled out in the form
IF OBJECT_ID('tempdb..#RequiredAnswersToFindNextFiltersToDisplay') IS NOT NULL
    DROP TABLE #RequiredAnswersToFindNextFiltersToDisplay

CREATE TABLE #RequiredAnswersToFindNextFiltersToDisplay (       
    FilterID INT,           
    FormAssociationID INT,  
    RequiredAnswerFilterID INT
)


-- this gets the RequiredAnswersIntoA String for joining on
INSERT INTO #RequiredAnswersToFindNextFiltersToDisplay (
    FilterID, FormAssociationID, RequiredAnswerFilterID
)


VALUES
( 35, 1, 0 ), 
( 36, 2, 35 ), 
( 37, 3, 36 ), 
( 38, 4, 36 ), 
( 39, 5, 37 ), 
( 40, 6, 38 ), 
( 41, 7, 38 ), 
( 42, 8, 38 ), 
( 43, 9, 38 ), 
( 44, 10, 40 ), 
( 45, 11, 41 ), 
( 46, 12, 42 ), 
( 47, 13, 43 ), 
( 48, 14, 47 ), 
( 49, 15, 47 )



;WITH ItemDataCTE(FilterID, FormAssociationID, RequiredAnswerFilterID, depth, sortcol, TreeListOfFilterIDs)
AS (
  -- anchor member
  SELECT FilterID, FormAssociationID, RequiredAnswerFilterID, 0, CAST(FilterID AS VARBINARY(900)) AS SortCol,
  CAST(FilterID AS VARCHAR(MAX)) AS TreeListOfFilterIDs
  FROM #RequiredAnswersToFindNextFiltersToDisplay
  WHERE RequiredAnswerFilterID = 0

  UNION ALL

  SELECT ID.FilterID, ID.FormAssociationID, ID.RequiredAnswerFilterID, M.depth + 1, CAST(M.SortCol + CAST(ID.FilterID AS BINARY(4)) AS VARBINARY(900)) SortCol,
  CAST(M.TreeListOfFilterIDs + ',' + CAST(ID.FilterID AS VARCHAR(50)) AS VARCHAR(MAX)) AS TreeListOfFilterIDs     
  FROM #RequiredAnswersToFindNextFiltersToDisplay ID      
  INNER JOIN ItemDataCTE AS M ON ID.RequiredAnswerFilterID = M.FilterID   
)

SELECT *
FROM ItemDataCTE
ORDER BY ItemDataCTE.sortcol

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用not exists向递归cte添加自联接:

SELECT *
FROM ItemDataCTE as c0
WHERE NOT EXISTS
(
    SELECT 1
    FROM ItemDataCTE AS c1
    WHERE c1.TreeListOfFilterIDs LIKE c0.TreeListOfFilterIDs +',%'
)
ORDER BY sortcol

结果:

FilterID    FormAssociationID   RequiredAnswerFilterID  depth   sortcol                         TreeListOfFilterIDs
39          5                   37                      3       00035000360003700039            35,36,37,39
44          10                  40                      4       0003500036000380004000044       35,36,38,40,44
45          11                  41                      4       0003500036000380004100045       35,36,38,41,45
46          12                  42                      4       0003500036000380004200046       35,36,38,42,46
48          14                  47                      5       000350003600038000430004700048  35,36,38,43,47,48
49          15                  47                      5       000350003600038000430004700049  35,36,38,43,47,49