如何获取递归 CTE 中生成的最后一条记录?

问题描述 投票:0回答:4

在下面的代码中,我使用 SQL Server 2005 中的递归 CTE(公用表表达式)来尝试查找基本层次结构的顶级父级。此层次结构的规则是每个 CustID 都有一个 ParentID,如果 CustID 没有父级,则 ParentID = CustID 并且它是最高级别。

DECLARE @LookupID int

--Our test value
SET @LookupID = 1

WITH cteLevelOne (ParentID, CustID) AS
(
        SELECT   a.ParentID, a.CustID
        FROM     tblCustomer AS a
        WHERE    a.CustID = @LookupID
    UNION ALL
        SELECT   a.ParentID, a.CustID
        FROM     tblCustomer AS a
        INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID
        WHERE c.CustID <> a.CustomerID
)

所以如果 tblCustomer 看起来像这样:

ParentID    CustID
5            5
1            8
5            4
4            1

我从上面的代码得到的结果是:

ParentID    CustID
4            1
5            4
5            5

我想要的只是结果的最后一行:

ParentID    CustID
5            5

如何返回 CTE 中生成的最后一条记录(这将是最高级别的 CustID)?

另请注意,此表中有多个不相关的 CustID 层次结构,因此我不能只执行 SELECT * FROM tblCustomer WHERE ParentID = CustID。我无法按 ParentID 或 CustID 订购,因为 ID 号与其在层次结构中的位置无关。

sql sql-server recursion common-table-expression
4个回答
3
投票

如果你只是想要最高的递归深度,你不能做这样的事情吗?然后,当你实际查询 CTE 时,只需查找具有 max(Depth) 的行?像这样:

DECLARE @LookupID int

--Our test value
SET @LookupID = 1;

WITH cteLevelOne (ParentID, CustID, Depth) AS
(
        SELECT   a.ParentID, a.CustID, 1
        FROM     tblCustomer AS a
        WHERE    a.CustID = @LookupID
    UNION ALL
        SELECT   a.ParentID, a.CustID, c.Depth + 1
        FROM     tblCustomer AS a
        INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID 
        WHERE c.CustID <> a.CustID
)
select * from CTELevelone where Depth = (select max(Depth) from CTELevelone)

或者,按照 Trevor 的建议,这可以与相同的 CTE 一起使用:

select top 1 * from CTELevelone order by Depth desc

我认为 CustomerID 不一定是您所描述的情况下想要订购的内容,但我对这个问题也不是很清楚。


1
投票

我不确定我完全理解这个问题,但只是为了破解它,你可以尝试:

SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC

假设 CustID 也按示例中的顺序排列,而不是类似 GUID 的内容。


0
投票

首先,如果任何父子相同,则 cte 将不会完成。由于它是递归 CTE,因此必须终止。如果 Parent 和 cust id 相同,循环将不会结束。

消息 530,第 16 级,状态 1,第 15 行 声明终止。在语句完成之前,最大递归 100 已用完。


0
投票

请停止终止语句,我知道最大递归。 它有可能如何知道我的循环在哪个级别(当前深度)?

喜欢:

   WITH cteLevelOne (ParentID, CustID, Depth) AS
    (
            SELECT   a.ParentID, a.CustID, 1
            FROM     tblCustomer AS a
            WHERE    a.CustID = @LookupID
        UNION ALL
            SELECT   a.ParentID, a.CustID, c.Depth + 1
            FROM     tblCustomer AS a
            INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID 
            WHERE c.CustID <> a.CustID
             **AND c.Depth = currentDepth -1** 

    )
    select * from CTELevelone where Depth = (select max(Depth) from CTELevelone)
© www.soinside.com 2019 - 2024. All rights reserved.