[英]How to present hierarchical data in SQL Server 2014
I have two tables Company
and CompanyRelationShip
.我有两个表
Company
和CompanyRelationShip
。
DECLARE @Company TABLE (
CompanyId INT
,RootCompanyId INT
,CompanyName VARCHAR(100)
)
INSERT INTO @Company
VALUES (2,2,'ROOT')
,(106,2,'ABC')
,(105,2,'CDF')
,(3,3,'ROOT2')
,(150,3,'YXZ')
,(151,3,'XZX')
DECLARE @CompanyRelationShip TABLE (
PrimaryCompanyId INT
,CompanyId INT
)
INSERT INTO @CompanyRelationShip
VALUES (2,2)
,(2,106)
,(2,105)
,(106,105)
,(3,3)
,(3,151)
,(3,150)
,(151,150)
I want the result in the below format我想要以下格式的结果
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
I have tried the below query to get the result我已经尝试了以下查询来获得结果
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
I would really appreciate a bit of help.我真的很感激一点帮助。
In my comment I asked you, why you would need the table @CompanyRelationShip
at all... This is just adding a hell of a lot of complexity and potentials for errors.在我的评论中,我问你,为什么你需要
@CompanyRelationShip
表......这只是增加了大量的复杂性和出错的可能性。
My suggestion relies on the first table alone.我的建议仅依赖于第一张桌子。 Look, how I've changed the parent IDs of 105 and 151 to place them below in the hierarchy.
看,我是如何更改 105 和 151 的父 ID 以将它们放在层次结构中的下方的。 Just to show the principles I've added a second child below 150 :
只是为了展示我在 150 以下添加了第二个孩子的原则:
DECLARE @Company TABLE (
CompanyId INT
,RootCompanyId INT
,CompanyName VARCHAR(100)
);
INSERT INTO @Company
VALUES (2,2,'ROOT')
,(106,2,'ABC')
,(105,106,'CDF')
,(3,3,'ROOT2')
,(150,3,'YXZ')
,(151,150,'XZX')
,(152,150,'Second below 150');
--the query --查询
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;
The result结果
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
The idea in short:简而言之这个想法:
RootId
and RootName
are just passed through to show up in your final set. RootId
和RootName
两列刚刚通过以显示在您的最终集合中。 The HierarchyLevel
is the position within the line, thus placing 105 within ROOT, but below 106. HierarchyLevel
是行内的位置,因此将 105 放置在ROOT内,但低于106。
Hope this helps...希望这可以帮助...
As told, the given structure is not the best choice and should be altered.如上所述,给定的结构不是最佳选择,应该进行更改。 But if you have to stick to this, you might try something along this:
但是,如果您必须坚持这一点,您可以尝试以下方法:
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;
This will first use a recursive CTE to find the children below their root companies and the will try to find the corresponding line in your relationship table.这将首先使用递归 CTE 来查找其根公司下面的子项,并尝试在您的关系表中找到相应的行。
If you use just SELECT *
instead of the column list you can see the full set.如果您只使用
SELECT *
而不是列列表,您可以看到完整的集合。 Using LEFT JOIN
will return NULL
, when the ON
claus is not met.当不满足
ON
子句时,使用LEFT JOIN
将返回NULL
。
COALESCE
will return the first non-NULL value, so - hopefully - the one you are after. COALESCE
将返回第一个非 NULL 值,所以 - 希望 - 你所追求的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.