Sql server 如何在SQL Server 2014中显示分层数据

Sql server 如何在SQL Server 2014中显示分层数据,sql-server,tsql,sql-server-2014,Sql Server,Tsql,Sql Server 2014,我有两张桌子,一张是公司的,另一张是友谊的 我想要以下格式的结果 CompanyId PrimayCompanyId PrimaryCompanyName RootCompanyId RootCompanyName 2 2 ROOT 2 ROOT 106 2 ROOT 2

我有两张桌子,一张是公司的,另一张是友谊的

我想要以下格式的结果

CompanyId   PrimayCompanyId PrimaryCompanyName  RootCompanyId   RootCompanyName
2                 2              ROOT               2               ROOT
106               2              ROOT               2               ROOT
105              106             ABC                2               ROOT
3                 3              ROOT2              3               ROOT2
151              3               ROOT2              3               ROOT2
150              151             XZX                3               ROOT2
我尝试了下面的查询以获得结果

WITH PrimayCompany
AS (
    SELECT CR.PrimaryCompanyId
        ,C.CompanyName
    FROM @CompanyRelationShip CR
    JOIN @Company C ON CR.CompanyId = CR.PrimaryCompanyId
    )
    ,RootCompany
AS (
    SELECT RootCompanyId
        ,CompanyName
    FROM @Company
    WHERE CompanyId = RootCompanyId
    )
SELECT C.CompanyId
    ,C.RootCompanyId
    ,RC.CompanyName
    ,CR.PrimaryCompanyId
    ,PC.CompanyName
FROM @Company C
LEFT JOIN @CompanyRelationShip CR ON C.CompanyId = CR.PrimaryCompanyId
LEFT JOIN PrimayCompany PC ON PC.PrimaryCompanyId = CR.PrimaryCompanyId
LEFT JOIN RootCompany RC ON RC.RootCompanyId = CR.PrimaryCompanyId

我真的非常感谢您的帮助。

在我的评论中,我问您,为什么您需要表格@CompanyRelationShip。。。这只是增加了很多复杂性和潜在的错误

我的建议仅依赖于第一张表。看,我是如何更改105和151的父ID以将它们放在层次结构的下面的。为了说明这些原则,我在150以下添加了第二个孩子:

-询问

WITH recCTE AS
(
    SELECT CompanyId AS [RootId],CompanyName AS [RootName],*,1 AS HierarchyLevel FROM @Company WHERE CompanyId=RootCompanyId
    UNION ALL
    SELECT rc.RootId,rc.RootName,c.*,rc.HierarchyLevel+1
    FROM @Company c
    INNER JOIN recCTE rc ON c.RootCompanyId=rc.CompanyId AND c.CompanyId<>rc.CompanyId
)
SELECT RootId
      ,RootName
      ,RootCompanyId AS [PrevId]
      ,CompanyId
      ,CompanyName
      ,HierarchyLevel 
FROM recCTE rc
ORDER BY RootId,HierarchyLevel;
简而言之:

我们使用递归CTE,这实际上是一个相当迭代的概念。 第一个选择锚从两个ID匹配的公司开始。 UNION ALL后的第二个SELECT通过连接到中间结果行拾取下一个级别 RootId和RootName这两列只是传递到最后一个集合中。 等级是线内的位置,因此将105置于根内,但低于106

希望这有助于

给定结构的一种解法 如上所述,给定的结构不是最佳选择,应该进行更改。但如果你必须坚持这一点,你可以尝试以下方法:

WITH recCTE AS
(
    SELECT CompanyId AS [RootId],CompanyName AS [RootName],*,1 AS HierarchyLevel FROM @Company WHERE CompanyId=RootCompanyId
    UNION ALL
    SELECT rc.RootId,rc.RootName,c.*,rc.HierarchyLevel+1
    FROM @Company c
    INNER JOIN recCTE rc ON c.RootCompanyId=rc.CompanyId AND c.CompanyId<>rc.CompanyId
)
SELECT rc.CompanyId
      ,rc.CompanyName  
      ,COALESCE(crs.PrimaryCompanyId,rc.RootCompanyId) AS ComputedPrevId
      ,COALESCE(c1.CompanyName,rc.RootName) AS ComputedPrevName
      ,rc.RootId
      ,rc.RootName
FROM recCTE rc
LEFT JOIN @CompanyRelationShip  crs ON rc.CompanyId=crs.CompanyId AND rc.RootCompanyId<>crs.PrimaryCompanyId
LEFT JOIN @Company c1 ON crs.PrimaryCompanyId=c1.CompanyId
ORDER BY rc.RootId,rc.HierarchyLevel;
这将首先使用递归CTE查找其根公司下面的子公司,并尝试在关系表中查找相应的行

如果只使用SELECT*而不是列列表,则可以看到完整的集合。 当不满足ON claus时,使用LEFT JOIN将返回NULL


COALESCE将返回第一个非空值,因此(希望如此)将返回您要查找的值。

任务是什么?要使用root 2获取所有记录?我不获取您的查询逻辑我已修改了查询。我想从Company表中获得每个公司的主公司和根公司的详细信息。CompanyId 105有两个PrimaryCompanyID 2和106。你将如何决定105的主要公司?顺便说一句:非常感谢你的提问,并给出了完整的答案。这使我们能够帮助更多的地点和了解您的问题…我得到了错误的结果。对于105,PrevId应该是106。请调查一下。@sasibhushan,对不起,不能反映这一点。。。在我的回答中,您可以看到结果,它显示了预期的PrevId=106,其中CompanyId=105。。。通过将106设置为其父级,公司105位于106之后……对不起,我看不到PrevId=106,其中companyId=105,还有一件事我现在无法更改公司表结构。所以我必须求助于同伴关系表。对不起,我得到了结果。但是我不能改变桌子的结构。有没有可能用上面的数据写下这个查询?非常感谢你的帮助。
WITH recCTE AS
(
    SELECT CompanyId AS [RootId],CompanyName AS [RootName],*,1 AS HierarchyLevel FROM @Company WHERE CompanyId=RootCompanyId
    UNION ALL
    SELECT rc.RootId,rc.RootName,c.*,rc.HierarchyLevel+1
    FROM @Company c
    INNER JOIN recCTE rc ON c.RootCompanyId=rc.CompanyId AND c.CompanyId<>rc.CompanyId
)
SELECT RootId
      ,RootName
      ,RootCompanyId AS [PrevId]
      ,CompanyId
      ,CompanyName
      ,HierarchyLevel 
FROM recCTE rc
ORDER BY RootId,HierarchyLevel;
RootId  RootName    PrevId  CompanyId   CompanyName     HierarchyLevel
2       ROOT        2       2           ROOT                1
2       ROOT        2       106         ABC                 2
2       ROOT        106     105         CDF                 3
3       ROOT2       3       3           ROOT2               1
3       ROOT2       3       150         YXZ                 2
3       ROOT2       150     151         XZX                 3
3       ROOT2       150     152         Second below 150    3
WITH recCTE AS
(
    SELECT CompanyId AS [RootId],CompanyName AS [RootName],*,1 AS HierarchyLevel FROM @Company WHERE CompanyId=RootCompanyId
    UNION ALL
    SELECT rc.RootId,rc.RootName,c.*,rc.HierarchyLevel+1
    FROM @Company c
    INNER JOIN recCTE rc ON c.RootCompanyId=rc.CompanyId AND c.CompanyId<>rc.CompanyId
)
SELECT rc.CompanyId
      ,rc.CompanyName  
      ,COALESCE(crs.PrimaryCompanyId,rc.RootCompanyId) AS ComputedPrevId
      ,COALESCE(c1.CompanyName,rc.RootName) AS ComputedPrevName
      ,rc.RootId
      ,rc.RootName
FROM recCTE rc
LEFT JOIN @CompanyRelationShip  crs ON rc.CompanyId=crs.CompanyId AND rc.RootCompanyId<>crs.PrimaryCompanyId
LEFT JOIN @Company c1 ON crs.PrimaryCompanyId=c1.CompanyId
ORDER BY rc.RootId,rc.HierarchyLevel;