首页 > 解决方案 > 通过仅重建您想要的部分树来加速 T-SQL CTE?

问题描述

我有一个非常简单的 ParentID (int) 和 ChildID (int) 表。问题是它有几千行长,而且许多 ChildID 是其他 ParentID 的 ParentID。

我感兴趣的只是构建所有这些共享 ID 的层次结构。然而,一些分支可能只有 2 或 3 层深,而其他分支可能有 30 层以上。

虽然所有数据都很重要,但只有某些分支(及其子分支)在特定时间是重要的。

我最初的尝试是“暴力破解”它并构建整个树,但它的效率极低且资源密集。

因此,我想知道如何调整我的基本非常简单/标准 CTE(使用前面提到的只有两个整数列的简单表)来选择这个非常复杂的树的特定分支,然后递归地构建分支的层次结构我想要到达最远的地方,而不必构建树的其余部分及其所有分支。

这可能吗?

作为旁注 - 由于数据量庞大,加上它只是数字数据的简单性,我无法猜测某个分支之后会发生什么(即,基本上没有顺序编号或任何提供提示的东西任何事情都可能超出我想要的分支我知道我需要从所有数据中提取,我只是不想浪费时间/资源来构建我不需要的分支)。

编辑:这是我的示例代码:

;WITH CTE
AS (
Select ChildID
    ,ParentID
    ,cast(ParentID as varchar(max)) as IDpath
From #TempTable

UNION ALL

Select B.ChildID
    ,B.ParentID
    ,cast(B.ParentID as varchar(max)) + '>' + A.IDpath as IDpath
From CTE A
    Inner Join #TempTable B on A.ParentID=B.ChildID
)
Select Distinct IDpath
From CTE
Where IDpath is not null

就数据而言,父 ID 和子 ID 是 1-10,000 之间的整数。有些父母有孩子,有些没有(在这些情况下,ChildID 为空)。

所以我的输出看起来像:

ParentID>ID>ID>ID>ID>ID>ChildID(中间的ID是他们父母的孩子,然后是后续孩子的父母等等)。

标签: sqlcommon-table-expression

解决方案


所以这是我用来解决我的问题的代码,以选择编号为 2220 的 ID 作为我的“主干”路径,我能够通过所有父/子 ID 将这个 ID 映射到我分支的最远叶子的层次结构。

现在我根本不是 SQL 编码方面的专家。坦率地说,我什至不擅长它,所以这可能不是解决问题的最佳方法(甚至不是一个彻底的解决方案,但考虑到我对结果的期望,它似乎对我有用)。

现在,如果 2220 不是另一个 ParentID 的 ChildID,我不确定这是否可行。我可能会稍后对其进行测试,但就目前而言,我正在获取我需要的数据。但是,如果这最终成为问题,我总是可以进行检查并将其作为 ChildID 插入,其 ParentID 为 0(因为我知道我的所有 ID 都是正整数)。

无论如何,这就是我更改代码以使其适合我的方式:

;WITH CTE
AS (
Select 1 as Level
    ,ChildID
    ,ParentID
    ,cast(ChildID as varchar(max)) as IDpath
From #TempTable

UNION ALL

Select Level + 1 as Level
    ,B.ChildID
    ,B.ParentID
    ,A.IDpath + '>' + cast(B.ChildID as varchar(max)) as IDpath
From CTE A
    Inner Join #TempTable B on A.ChildID=B.ParentID
Where Level = 1
    or (Level > 1 and IDpath like '2220%')
)
Select Distinct IDpath
From CTE
Where left(IDPath,4) = '2220'

现在,如果有专业知识的人可以评论这个“修复”的质量并且它是否合理(或者如果我遗漏了什么),我将不胜感激。我不想因为我天真地假设这是一个好的(足够)修复而意外地用垃圾修复毒害大众。


推荐阅读