如何获取递归 CTE 中生成的最后一条记录?
-
09-06-2019 - |
题
在下面的代码中,我使用 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 号与其在层次结构中的位置无关。
解决方案
如果您只想获得最高的递归深度,您不能这样做吗?然后,当您实际查询 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 不一定是您想要订购的内容,但我对这个问题也不是很清楚。
其他提示
我不确定我完全理解这个问题,但只是为了破解它,你可以尝试:
SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC
假设 CustID 也如示例中所示有序,而不是类似 GUID 的内容。
首先,如果任何父子相同,则 cte 将不会完成。由于它是递归 CTE,因此必须终止。如果 Parent 和 cust id 相同,循环将不会结束。
MSG 530,16级,状态1,第15行终止声明。在语句完成之前,最大递归次数 100 已用尽。
不隶属于 StackOverflow