【问题标题】:How do you get the last record generated in a recursive CTE?如何获得递归 CTE 中生成的最后一条记录?
【发布时间】:2010-09-07 07:29:00
【问题描述】:

在下面的代码中,我在 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


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      如果你只是想要最高的递归深度,你不能这样做吗?那么,当你实际查询 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)
      

      或者,根据特雷弗的建议,这可以与相同的 CTE 一起使用:

      select top 1 * from CTELevelone order by Depth desc
      

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

      【讨论】:

        【解决方案3】:

        我不确定我是否完全理解这个问题,但你可以尝试破解并削减它:

        SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC
        

        假设 CustID 也像示例中那样按顺序排列,而不是类似于 GUID。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-09-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-23
          • 2011-04-25
          • 2023-03-16
          相关资源
          最近更新 更多