我在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
答案 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