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
这很好,因为无论表架构如何更改,只要有[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
这样做效果很好,但是除了前一个查询的主要优点,因为最后选择*也会给我一个级别.有没有其他方法可以指定一个级别,但也通常从表中选择所有列?提前致谢.
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)
编辑:
回答注释中的问题,不,你不能抑制在递归时间比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;
假设您没有计划更改分层或主键字段,这应该与上面的内容一样通用.
| 归档时间: | 
 | 
| 查看次数: | 7341 次 | 
| 最近记录: |