【问题标题】:Recursively get last record from same table parent child从同一个表父子递归获取最后一条记录
【发布时间】:2019-03-26 17:51:54
【问题描述】:

我想从同一张表中获取最后一个参考 ID。我有下表。

 ID   UserId   DelegatedToUserId
 1      100       101
 2      101       102
 3      102       103
 4      103       NULL
 5      104       109

我就是想不通。我知道我想要什么,只是无法在屏幕上显示出来。因此,当我要求 100 查询时应返回 103,当我再次询问 101 或 102 时应返回 103。当用户输入 104 时应返回 109

当我要求 103 时,它应该返回 103,因为没有代表。

这可以在单个 sql 查询中完成吗?

【问题讨论】:

  • "这可以在单个 sql 查询中完成吗?" 是的,常见的方法是使用递归通用表表达式 (rCTE)。您以前使用过这些,或对它们进行过任何研究吗?
  • 此外,如果输入104,查询将不会返回任何行,因为您的表中没有用户109。由于用户 104 没有父级(109 不存在),因此它们是孤儿,因此当您返回不存在的“顶级父行”时。这与103 不同,因为它明确指出它没有父级;它可以被识别为“根”。

标签: sql sql-server sql-optimization


【解决方案1】:

这可以在单个 sql 查询中完成吗?

如果您不知道层次结构可以达到什么级别,则需要使用递归CTE。如果只是 1 级或 2 级,您可以在单个查询中不使用递归 CTE

您可以使用递归CTE 来获得所需的输出。

;WITH mytest 
     AS (SELECT P.userid, 
                P.delegatedtouserid, 
                1 AS LVL 
         FROM   @table P 
         WHERE  userid = 100 
         UNION ALL 
         SELECT P1.userid, 
                P1.delegatedtouserid, 
                M.lvl + 1 AS LVL 
         FROM   @table P1 
                INNER JOIN mytest M 
                        ON M.delegatedtouserid = P1.userid) 

SELECT TOP 1 WITH ties * 
FROM   mytest 
ORDER  BY Row_number() OVER (ORDER BY lvl DESC); 

注意:将@table 替换为您的实际表名。

Online Demo

【讨论】:

    【解决方案2】:

    就个人而言,我会这样做:

    DECLARE @UserID int = 103;
    
    WITH VTE AS
        (SELECT *
         FROM (VALUES (1, 100, 101),
                      (2, 101, 102),
                      (3, 102, 103),
                      (4, 103, NULL),
                      (5, 104, 109)) AS V (ID, UserID, DelegatedToUserID) ),
    rCTE AS
        (SELECT V.ID,
                V.UserID,
                V.DelegatedToUserID
         FROM VTE V
         WHERE UserID = @UserID
         UNION ALL
         SELECT V.ID,
                V.UserID,
                V.DelegatedToUserID
         FROM rCTE r
              JOIN VTE V ON r.DelegatedToUserID = V.UserID)
    SELECT *
    FROM rCTE
    WHERE rCTE.DelegatedToUserID IS NULL;
    

    然而,正如我在 cmets 中提到的,传递 104 将返回 no rows,因为用户 109 不存在于表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 2014-12-09
      • 2014-03-06
      • 2015-01-29
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多