在 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 值函数并实施类似的解决方案,如 所述。
我有一个用户 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 值函数并实施类似的解决方案,如