【问题标题】:SQL Top parent record in hierarchySQL 层次结构中的顶级父记录
【发布时间】:2012-03-01 22:36:30
【问题描述】:

我有一个结构表:

CompanyID、CompanyName、LinkedCompanyID

以便多个公司可以在一个层次结构中链接

例如

CompanyID, CompanyName, LinkedCompanyID
1          Company A,   NULL
2          Company B,   1
3          Company C,   2
4          Company D,   2
5          Company E,   4
6          Company F,   3
7          Company G,   NULL

我想要一个查询以返回每个公司的顶级父级

CompanyID, CompanyName, ToplevelParentID
1          Company A,   NULL (or 1 I don't mind)
2          Company B,   1
3          Company C,   1
4          Company D,   1
5          Company E,   1
6          Company F,   1
7          Company G,   NULL (or 7 I don't mind)

我已经研究过使用递归 CTE 表达式,但我能找到的所有示例都返回从父级向下的层次结构列表,而不是最顶层的父级。

任何人都可以提供任何指针或示例查询

【问题讨论】:

  • 强烈建议:添加一个跟踪“顶部容器”的字段。我在类似的场景中这样做(并且一些 intetim knwdes 是它们自己的容器 - 例如 CMS:将结构过滤到文档,这是一个容器,然后在文档中构建结构。这会变得容易得多。

标签: sql sql-server tsql common-table-expression


【解决方案1】:

这仍然可以通过递归 CTE 来实现:

CREATE TABLE #Test (CompanyID INT, CompanyName VARCHAR(20), LinkedCompanyID INT)
INSERT INTO #Test
SELECT  1, 'Company A',   NULL UNION
SELECT  2, 'Company B',   1 UNION
SELECT  3, 'Company C',   2 UNION
SELECT  4, 'Company D',   2 UNION
SELECT  5, 'Company E',   4 UNION
SELECT  6, 'Company F',   3 UNION
SELECT  7, 'Company G',   NULL

;WITH CTE AS
(   SELECT  *, 0 [Level]
    FROM    #Test
    UNION ALL
    SELECT  CTE.CompanyID, CTE.CompanyName, #Test.LinkedCompanyID, Level + 1
    FROM    CTE
            INNER JOIN #Test
                ON CTE.LinkedCompanyID = #Test.CompanyID
    WHERE   #Test.LinkedCompanyID IS NOT NULL
)

SELECT  c.CompanyID, c.CompanyName, c.LinkedCompanyID
FROM    (   SELECT  *, MAX([Level]) OVER (PARTITION BY CompanyName) [MaxLevel]
            FROM    CTE
        ) c
WHERE   MaxLevel = Level

DROP TABLE #Test

【讨论】:

  • 太完美了。所以我需要使用 CROSS APPLY 和 CTE。我了解其中的 CTE 部分,您介意解释一下交叉应用的作用吗
  • 最后的查询只是获取最后一次 CTE 递归插入的行。实现这一目标的方法不止一种(INNER JOIN,EXISTS),但我认为在这种情况下,使用 OVER 函数是最有效的方法。如果您改为 SELECT * FROM CTE,您应该更好地了解最终查询如何将输出限制到顶级公司。仅使用子查询 C 是因为窗口函数不能出现在 WHERE 子句中。
【解决方案2】:

试试这个:

Select * , (select CompanyName from  Company C_aux where C_Main.LinkedCompanyID = C_aux.CompanyID) as ToplevelParentID
from Company C_Main

【讨论】:

  • 谢谢,但这只会返回最近的父级而不是顶级父级
猜你喜欢
  • 2021-07-05
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
相关资源
最近更新 更多