当前位置: 首页 > 面试题库 >

查找表的每一行的顶级父级[SQL Server 2008]

东方琪
2023-03-14
问题内容

我有以下两个表

表人

Id   Name
   1    A
   2    B
   3    C
   4    D
   5    E

表关系层次结构

ParentId   CHildId
   2         1
   3         2
   4         3

这将形成树状结构

      D
      |
      C
      |
      B
      |
      A

ParentId和ChildId是人员表的ID列的外键

我需要编写可以获取顶级父级(即每个人的根源)的SQL。

遵循CTE可以针对每个用户执行此操作。我将其转换为一个功能,并为Person的每一行运行了它。我在Person表中大约有3k行,大约需要10秒。任何人都可以建议一种可以减少花费的方法。问题是CTE运行3k次后运行的功能

DECLARE @childID INT 
SET @childID  = 1 --chield to search

;WITH RCTE AS
(
SELECT *, 1 AS Lvl FROM RelationHierarchy 
WHERE ChildID = @childID

UNION ALL

SELECT rh.*, Lvl+1 AS Lvl FROM dbo.RelationHierarchy rh
INNER JOIN RCTE rc ON rh.CHildId = rc.ParentId
 )
SELECT TOP 1 id, Name
FROM RCTE r
inner JOIN dbo.Person p ON p.id = r.ParentId
ORDER BY lvl DESC

问题答案:

我还更新了原始问题的答案,但请放心,这里也有一份副本:

;WITH RCTE AS
(
    SELECT  ParentId, ChildId, 1 AS Lvl FROM RelationHierarchy

    UNION ALL

    SELECT rh.ParentId, rc.ChildId, Lvl+1 AS Lvl 
    FROM dbo.RelationHierarchy rh
    INNER JOIN RCTE rc ON rh.ChildId = rc.ParentId
)
,CTE_RN AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY r.ChildID ORDER BY r.Lvl DESC) RN
    FROM RCTE r

)
SELECT pc.Id AS ChildID, pc.Name AS ChildName, r.ParentId, pp.Name AS ParentName
FROM dbo.Person pc 
LEFT JOIN CTE_RN r ON pc.id = r.CHildId AND  RN =1
LEFT JOIN dbo.Person pp ON pp.id = r.ParentId

SQLFiddle演示

请注意,稍有不同是在CTE的递归部分中。现在,每次从锚点部分重写ChildID。此外,还添加了ROW_NUMBER()函数(和新的CTE),以在最后获得每个孩子的顶层信息。

编辑-版本2

找到第一个查询的性能问题后,这是一个改进的版本。从上到下,而不是其他方式-消除CTE中多余的行的创建,在大量递归时应该更快得多:

;WITH RCTE AS
(
    SELECT  ParentId, CHildId, 1 AS Lvl FROM RelationHierarchy r1
    WHERE NOT EXISTS (SELECT * FROM RelationHierarchy r2 WHERE r2.CHildId = r1.ParentId)

    UNION ALL

    SELECT rc.ParentId, rh.CHildId, Lvl+1 AS Lvl 
    FROM dbo.RelationHierarchy rh
    INNER JOIN RCTE rc ON rc.CHildId = rh.ParentId
)
SELECT pc.Id AS ChildID, pc.Name AS ChildName, r.ParentId, pp.Name AS ParentName
FROM dbo.Person pc 
LEFT JOIN RCTE r ON pc.id = r.CHildId
LEFT JOIN dbo.Person pp ON pp.id = r.ParentId

SQLFiddle演示



 类似资料:
  • 问题内容: 给出下表 给定一个,我需要找到其顶级父级()。 每天执行50-100次此查询。当前有100-200行(将来可能会更多)。多达8个层次的深度。我在考虑三种选择: 使用递归方法 创建一个视图 添加另一列(最不满意) 哪个效率最高? 问题答案: SQL2008 +: 为了存储层次结构,SQL Server包含HIERARCHYID数据类型。可以将上述数据“转换为”以使用“值”: 转换后,我将

  • 问题内容: 在这种情况下,需要将元素滚动到视口中。问题是我不知道哪个元素是可滚动的。例如,在“纵向”中,身体是可滚动的,在“横向”中,身体是其他的元素(还有更多情况会更改可滚动的元素) 现在的问题是,给定需要滚动到视口中的元素,找到其第一个可滚动父级的最佳方法是什么? 我在这里设置了一个演示。使用按钮,您可以在两种不同情况之间切换 主体可以滚动或 有什么建议么 ? 问题答案: 只需检查滚动条是否可

  • 最有效的方法是只使用纯javascript查找特定父元素的子元素(带有类或ID)。没有jQuery或其他框架。 在这种情况下,我需要找到parent的child1或child2,假设DOM树中可以有多个child1或child2类元素。我只想要父母的元素

  • 我想知道是否有一种简单的方法可以从特定的窗口获得所有的顶层,包括顶层内的顶层。在下面的代码中,我留下了一个我想做的例子: Tkinter中是否有实现这一点的内置功能?

  • 问题内容: 我有一个具有以下字段的MySQL表: 其中父字段表示上层ID。例如,水果id是1,橙色是水果之一,因此父对象是1。 但是我想做一个有效的MySQL查询来获取所有记录,格式为parent-> children-> parent-> children格式。我怎样才能做到这一点? 查询的结果记录应类似于: 问题答案: 您需要mysql不支持的递归联接。您唯一可以做的就是确定最大深度(由于p-

  • 我正在研究一种寻找阳极父级的方法。我从根部开始,然后沿着叶子往下走,只要它们不是空的,不是孩子的节点。 下面是我的代码,它有点乱,因为我试着测试它看看哪里出了问题。