Oce*_*t20 5 sql sql-server sql-server-2005 common-table-expression
目前,我们有一个存储过程,通过执行以下操作,从其原始模式中的表返回数据:
WITH CTE AS
(
-- Start CTE off by selecting the id that was provided to stored procedure.
SELECT *
FROM [dbo].[TestTable]
WHERE [Id] = 1
-- Recursively add tasks that are children of records already found in previous iterations.
UNION ALL
SELECT t.*
FROM [dbo].[TestTable] as t
INNER JOIN CTE as tcte
ON t.[ParentId] = tcte.[Id]
)
SELECT *
FROM CTE
Run Code Online (Sandbox Code Playgroud)
这很好,因为无论表架构如何更改,只要有[Id]和[ParentId]列,我就不必更新此存储过程.我想做类似的事情,但也能够动态指定递归的深度.我看到这样做的唯一方法是添加一个Level/Depth标识符,如下所示:
WITH CTE AS
(
-- Start CTE off by selecting the task that was provided to stored procedure.
SELECT *, 0 as [Level]
FROM [dbo].[TestTable]
WHERE [Id] = 1
-- Recursively add tasks that are children of parent tasks that have already been found in previous iterations.
UNION ALL
SELECT t.*, [Level] + 1
FROM [dbo].[TestTable] as t
INNER JOIN CTE as tcte
ON t.[ParentId] = tcte.[Id]
WHERE [Level] < 2
)
SELECT *
FROM CTE
Run Code Online (Sandbox Code Playgroud)
这样做效果很好,但是除了前一个查询的主要优点,因为最后选择*也会给我一个级别.有没有其他方法可以指定一个级别,但也通常从表中选择所有列?提前致谢.
mwi*_*ahl 13
如果你想对你的级别字段做的只是限制递归的次数,你应该能够使用MAXRECURSION查询提示,如下所示:
WITH Department_CTE AS
(
SELECT
DepartmentGroupKey,
ParentDepartmentGroupKey,
DepartmentGroupName
FROM dimDepartmentGroup
WHERE DepartmentGroupKey = 2
UNION ALL
SELECT
Child.DepartmentGroupKey,
Child.ParentDepartmentGroupKey,
Child.DepartmentGroupName
FROM Department_CTE AS Parent
JOIN DimDepartmentGroup AS Child
ON Parent.ParentDepartmentGroupKey = Child.DepartmentGroupKey
)
SELECT * FROM Department_CTE
OPTION (MAXRECURSION 2)
Run Code Online (Sandbox Code Playgroud)
编辑:
回答注释中的问题,不,你不能抑制在递归时间比MAXRECURSION设置允许的时间更多的错误.如果我理解正确,你可以这样做:
WITH CTE AS
(
-- Start CTE off by selecting the task that was provided to stored procedure.
SELECT Id, 0 as [Level]
FROM [dbo].[TestTable]
WHERE [Id] = 1
-- Recursively add tasks that are children of parent tasks that have already been found in previous iterations.
UNION ALL
SELECT t.Id, [Level] + 1
FROM [dbo].[TestTable] as t
INNER JOIN CTE as tcte
ON t.[ParentId] = tcte.[Id]
WHERE [Level] < 2
),
CTE2 AS
(
SELECT TestTable.*
FROM CTE
INNER JOIN TestTable ON CTE.Id = TestTable.Id
)
SELECT * FROM CTE2;
Run Code Online (Sandbox Code Playgroud)
假设您没有计划更改分层或主键字段,这应该与上面的内容一样通用.
| 归档时间: |
|
| 查看次数: |
7341 次 |
| 最近记录: |