You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多父列层级记录排序:Recursive CTE的修改方案及示例

多父列自关联表的递归CTE实现需求

我有一张自关联表,包含2个(可能更多)外键列用于定义记录间的层级关系,表结构及数据如下:

Id名称Parent1__cParent2__c
a00Hu000014KBJrIAO祖父节点NULLNULL
a00Hu000014KBJwIAO父节点1a00Hu000014KBJrIAONULL
a00Hu000014KBK1IAO父节点2a00Hu000014KBJrIAONULL
a00Hu000014KBK6IAO子节点1_1a00Hu000014KBJwIAONULL
a00Hu000014KBK7IAO孙节点1_1_1a00Hu000014KBK6IAOa00Hu000014KBK1IAO
a00Hu000014KBvaIAG子节点2_2NULLa00Hu000014KBK1IAO
a00Hu000014KBvfIAG孙节点2_2_2a00Hu000014KBJwIAOa00Hu000014KBvaIAG
a00Hu000014KBvkIAG孙节点1_1_2a00Hu000014KBK6IAONULL

我已经实现了单父列(Parent1__c)的递归CTE,但不知道如何修改以同时支持Parent1__c和Parent2__c两个父列,最终希望按层级对记录排序,预期结果如下:

IdRecordHierarchyLevel
a00Hu000014KBJrIAO0
a00Hu000014KBJwIAO1
a00Hu000014KBK1IAO1
a00Hu000014KBK6IAO2
a00Hu000014KBvaIAG2
a00Hu000014KBvfIAG3
a00Hu000014KBvkIAG3
a00Hu000014KBK7IAO3

之前用C#递归查询会产生大量请求,对百万级数据集不友好,希望用原生SQL的递归CTE解决。现有单父列递归CTE代码如下:

With Children 
AS (
    SELECT 
        Id,
        Name,
        Parent1__c,
        Parent2__c,
        0 AS Level
    FROM CustomSelfRel__c
    WHERE Id = 'a00Hu000014KBJrIAO' AND NSPRemoved IS NULL

    UNION ALL

    SELECT
        T.Id,
        T.Name,
        T.Parent1__c,
        T.Parent2__c,
        Level + 1 AS Level
    FROM CustomSelfRel__c AS T
    JOIN Children  C ON C.Id = T.Parent1__c
) SELECT
    *
FROM
    Children;

多父列递归CTE解决方案

要支持多个父列,核心是在递归关联时同时匹配所有可能的父列,并且需要避免重复处理同一记录(因为一个子节点可能同时属于多个父节点)。以下是修改后的递归CTE代码:

WITH Hierarchy AS (
    -- 锚点成员:根节点
    SELECT 
        Id,
        Name,
        Parent1__c,
        Parent2__c,
        0 AS RecordHierarchyLevel,
        -- 用字符串记录已访问的节点,避免重复处理
        CAST(',' + Id + ',' AS VARCHAR(MAX)) AS VisitedNodes
    FROM CustomSelfRel__c
    WHERE Id = 'a00Hu000014KBJrIAO' AND NSPRemoved IS NULL

    UNION ALL

    -- 递归成员:匹配所有父列的子节点
    SELECT
        T.Id,
        T.Name,
        T.Parent1__c,
        T.Parent2__c,
        H.RecordHierarchyLevel + 1 AS RecordHierarchyLevel,
        -- 更新已访问节点集合
        H.VisitedNodes + T.Id + ',' AS VisitedNodes
    FROM CustomSelfRel__c AS T
    JOIN Hierarchy H 
        ON (H.Id = T.Parent1__c OR H.Id = T.Parent2__c)
        -- 确保当前节点未被访问过,避免循环和重复
        AND CHARINDEX(',' + T.Id + ',', H.VisitedNodes) = 0
)
-- 最终查询:去重并按层级排序
SELECT DISTINCT
    Id,
    RecordHierarchyLevel
FROM Hierarchy
ORDER BY RecordHierarchyLevel, Id;

关键修改说明

  • 多父列关联条件:在递归JOIN时,用OR同时匹配Parent1__c和Parent2__c,确保所有通过任一父列关联的子节点都能被纳入层级。
  • 避免重复与循环:新增VisitedNodes字段记录已处理的节点ID,通过CHARINDEX检查当前节点是否已被访问,防止同一节点被多次处理(比如孙节点1_1_1同时属于两个父节点),也避免潜在的循环引用问题。
  • 去重与排序:最终查询使用DISTINCT去除重复记录,然后按RecordHierarchyLevel排序,完全符合预期结果要求。

结果验证

执行上述代码后,将得到与预期一致的层级排序结果,且能高效处理百万级数据集,避免了应用层递归的性能瓶颈。


内容的提问来源于stack exchange,提问作者Ravi Teli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:57:09