在下面的代码中,我在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号与层次结构中的位置无关。
答案 0 :(得分:2)
如果你只是想要最高的递归深度,你不能做这样的事情吗?那么,当你实际查询CTE时,只需查找具有max(深度)的行?像这样:
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)
或者,根据特雷弗的建议,这可以与相同的CTE一起使用:
select top 1 * from CTELevelone order by Depth desc
我不认为在您描述的情况下,CustomerID不一定是您想要订购的,但我对此问题也不是很清楚。
答案 1 :(得分:1)
我不确定我是否完全理解这个问题,但只是为了破解&amp;你可以尝试一下:
SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC
这假设CustID也按照示例中的顺序排列,而不是像GUID那样。
答案 2 :(得分:0)
如果任何父子项相同,则首先不会完成cte。由于它是递归CTE,因此必须终止。如果Parent和cust id相同,则循环不会结束。
Msg 530,Level 16,State 1,Line 15 声明终止。在语句完成之前,最大递归100已经用尽。