在 SQL 服务器中将 CTE 转换为临时 table 以获得所有可能的父级

Conversion of CTE to temp table in SQL Server to get All Possible Parents

我有一个用户 table,我在其中维护父子关系,我想生成包含所有用户 ID 及其父 ID 和所有可能的分层父级的结果,作为逗号分隔的字符串。

我的table结构如下

CREATE TABLE [hybarmoney].[Users](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,   
    [USERID] [nvarchar](100) NULL,
    [REFERENCEID] [bigint] NULL 
)

我使用下面的 CTE

得到结果
;WITH Hierarchy (
    ChildId
    ,ChildName
    ,ParentId
    ,Parents
    )
AS (
    SELECT Id
        ,USERID
        ,REFERENCEID
        ,CAST('' AS VARCHAR(MAX))
    FROM hybarmoney.Users AS FirtGeneration
    WHERE REFERENCEID = 0

    UNION ALL

    SELECT NextGeneration.ID
        ,NextGeneration.UserID
        ,Parent.ChildId
        ,CAST(CASE 
                WHEN Parent.Parents = ''
                    THEN (CAST(NextGeneration.REFERENCEID AS VARCHAR(MAX)))
                ELSE (Parent.Parents + ',' + CAST(NextGeneration.REFERENCEID AS VARCHAR(MAX)))
                END AS VARCHAR(MAX))
    FROM hybarmoney.Users AS NextGeneration
    INNER JOIN Hierarchy AS Parent ON NextGeneration.REFERENCEID = Parent.ChildId
    )
SELECT *
FROM Hierarchy
ORDER BY ChildId
OPTION (MAXRECURSION 0)

但是我有 MAXRECURSION 的限制,当我用谷歌搜索时,我知道临时 tables 是一个替代解决方案,但我无法做到这一点 而且我也不想获得所有可能的顶级父级,为了我的目的,我想为每个用户找到 15 个等级的父级。如果可能的话,是否可以将 temp tables 用于我的目的如何。

如果有更好的解决方案,我使用流动查询得到了相同的结果

Create PROC UspUpdateUserAndFiftenLevelIDs (@UserID BIGINT)
AS
BEGIN
    DECLARE @REFERENCEIDString NVARCHAR(max)

    SET @REFERENCEIDString = ''

    DECLARE @ReferenceID BIGINT

    SET @ReferenceID = @UserID

    DECLARE @Count INT

    SET @Count = 0

    WHILE (@count < 15)
    BEGIN
        SELECT @ReferenceID = U.REFERENCEID
            ,@REFERENCEIDString = @REFERENCEIDString + CASE 
                WHEN @REFERENCEIDString = ''
                    THEN (CAST(U.REFERENCEID AS VARCHAR(100)))
                ELSE (',' + CAST(U.REFERENCEID AS VARCHAR(MAX)))
                END
        FROM hybarmoney.Users U
        WHERE U.ID = @ReferenceID

        SET @Count = @Count + 1
    END
        SELECT @UserID
            ,@REFERENCEIDString


END

为了仅获得 N 级别的 CTE,您可以做的是创建一个额外的列,您可以在其中跟踪每个级别。

;WITH Hierarchy (
    ChildId
    ,ChildName
    ,ParentId
    ,LEVEL
    ,Parents
    )
AS (
    SELECT Id
        ,USERID
        ,REFERENCEID
        ,0 AS LEVEL
        ,CAST('' AS VARCHAR(MAX))
    FROM hybarmoney.Users AS FirtGeneration
    WHERE REFERENCEID = 0

    UNION ALL

    SELECT NextGeneration.ID
        ,NextGeneration.UserID
        ,Parent.ChildId
        ,LEVEL+1 AS LEVEL
        ,CAST(CASE 
                WHEN Parent.Parents = ''
                    THEN (CAST(NextGeneration.REFERENCEID AS VARCHAR(MAX)))
                ELSE (Parent.Parents + ',' + CAST(NextGeneration.REFERENCEID AS VARCHAR(MAX)))
                END AS VARCHAR(MAX))
    FROM hybarmoney.Users AS NextGeneration
    INNER JOIN Hierarchy AS Parent ON NextGeneration.REFERENCEID = Parent.ChildId
    )
SELECT *
FROM Hierarchy
WHERE LEVEL <= 15
ORDER BY ChildId
OPTION (MAXRECURSION 0)

如果我正确理解您的以下陈述:"for my purpose I want to find 15 levels of hierarchical parents for each users",您实际上是指 单个用户 的 15 级分层父级(在您的情况下 REFERENCEID=0).

如果您希望它为您的 hybarmoney.Users table 中的每个用户 生成一个包含 15 个分层父级的列表 ,则将您的 CTE 移动到 table 值函数并实施类似的解决方案,如 所述。