返回父组件下多个级别的所有组件
Returning all components multiple levels under a parent component
我有一个分层数据库,我想从中 return 具有 特定 公共父组件的资产中的所有组件。
tableastComponents
中的组件通过 ParentComponentId
链接到它们的父组件,引用其他组件的 Id
。然而,这只显示父级上一级。
此外,所有组件都通过 AssetId
键链接到资产,链接到 table astAssets
.
中的 Id
键
我能够进行一个简单的查询(如下)来检索特定资产的所有组件。我不知道如何 return 来自共享相同父组件的特定资产的所有组件。此父组件可能(相对于子组件)1 到多个级别。
Select C.Id, C.Code, ParentC.Id, ParentC.Code, A.Code
From astComponents C
Join astAssets A ON A.Id = C.AssetId
Join astComponents ParentC ON ParentC.Id = C.ParentComponentId
Where A.Code = '2018100000'
以上查询 return 的组件及其上一级的父组件。如果我指定父代码,它只会 return 子组件比这个指定组件低一级,而不是所有级别。
所以如果我没有理解错的话,你有一个已知的父组件,和一个已知的资产代码。使用它们,您想构建一个树,覆盖从父组件到相关资产的 路径 (缺少更好的词)?
这是一个尝试。我们首先构建一些用于测试的虚拟数据:
declare @component table (
id int primary key,
code nvarchar(50) not null,
parent_id int null,
asset_id int null
)
declare @asset table (
id int primary key,
code nvarchar(50)
)
insert into @asset values (1, '2018100000')
insert into @asset values (2, '2019100000')
insert into @component values(1, 'root', null, null)
insert into @component values(2, 'c1', 1, null)
insert into @component values(3, 'c2', 1, null)
insert into @component values(4, 'c3', 1, null)
insert into @component values(5, 'c2_c1', 3, null)
insert into @component values(6, 'c2_c2', 3, 1)
insert into @component values(7, 'c2_c1_c1', 5, 2)
insert into @component values(8, 'c2_c1_c2', 5, 1)
insert into @component values(9, 'c2_c1_c2_c1', 8, 2)
insert into @component values(9, 'c2_c1_c1_c1', 7, 1)
然后我们声明几个递归 CTE
:s 并使用它们来获取输出:
declare @specParentId int
declare @assetCode nvarchar(50)
set @specParentId = 3
set @assetCode = '2018100000'
;with compRecurseDown as (
select c.id, c.code, parent_id, 0 as level, c.asset_id
from @component c
where c.id = @specParentId
union all
select c.id, c.code, c.parent_id, p.level + 1, c.asset_id
from @component c
join compRecurseDown p on c.parent_id = p.id
), assetRecurseUp as (
select c.*
from @asset a
join @component c on a.id = c.asset_id
where a.code = @assetCode
union all
select c.*
from @component c
join assetRecurseUp p on p.parent_id = c.id
)
select crd.*, a.code as asset_code
from compRecurseDown crd
left outer join @asset a on crd.asset_id = a.id
where crd.id in (
select id from assetRecurseUp
)
order by level
在这种情况下,我们要在 ID 为 3
的组件下查找资产 2018100000
。结果:
| id | code | parent_id | level | asset_id | asset_code |
|----|----------|-----------|-------|----------|------------|
| 3 | c2 | 1 | 0 | NULL | NULL |
| 5 | c2_c1 | 3 | 1 | NULL | NULL |
| 6 | c2_c2 | 3 | 1 | 1 | 2018100000 |
| 8 | c2_c1_c2 | 5 | 2 | 1 | 2018100000 |
那么这是如何工作的呢?首先我们声明 compRecurseDown
CTE。它使用已知的父组件作为其anchor
,然后递归查找该节点下的所有子注释。
assetRecurseUp
CTE 首先查找所有链接到已知资产的组件。然后它基于此递归添加所有父节点。
最后我们查询这两者的组合,产生最终的结果集。
好的,没有任何数据可以使用,这里有很多猜测。我创建了一些数据:
DECLARE @astComponents TABLE (Id INT, Code VARCHAR(50), ParentComponentId INT, AssetId INT);
DECLARE @astAssets TABLE (Id INT, Code VARCHAR(50));
INSERT INTO @astAssets SELECT 1, '2018100000';
INSERT INTO @astAssets SELECT 2, '2018100001';
INSERT INTO @astComponents SELECT 1, 'Power Supply', NULL, 1;
INSERT INTO @astComponents SELECT 2, 'Fan', 1, NULL;
INSERT INTO @astComponents SELECT 3, 'Screw', 2, NULL;
INSERT INTO @astComponents SELECT 4, 'Heat Tape', 1, NULL;
INSERT INTO @astComponents SELECT 5, 'Magnet', NULL, 2;
INSERT INTO @astComponents SELECT 6, 'Iron', 5, NULL;
你可以用这个做的是使用递归映射出所有共享一个公共父级的组件,并记录它们属于哪个资产,例如:
--Make a recursive list of components sharing a common parent
WITH cte AS (
SELECT
Id,
ParentComponentId,
AssetId
FROM
@astComponents
WHERE
ParentComponentId IS NULL
UNION ALL
SELECT
c.Id,
c.ParentComponentId,
cte.AssetId
FROM
@astComponents c
INNER JOIN cte ON cte.Id = c.ParentComponentId)
SELECT * FROM cte;
我打赌你的桌子不是这样工作的,所以你需要调整它以适应。就我而言,我得到以下结果:
Id ParentComponentId AssetId
1 NULL 1
5 NULL 2
6 5 2
2 1 1
4 1 1
3 2 1
所以我可以看到组件 #1 和 #5 没有父组件,所以这些是 "top level" 个组件,我还可以看到哪些组件 link 属于哪些资产。
现在只需将查询的 SELECT * FROM cte
部分替换为如下内容即可:
SELECT
cte.Id,
c.Code,
c.ParentComponentId
FROM
cte
INNER JOIN @astComponents c ON c.Id = cte.Id
INNER JOIN @astAssets a ON a.Id = cte.AssetId
WHERE
a.Code = '2018100000';
给我共享一个父项的所有组件,其中父项的资产代码为 201810000:
Id Code ParentComponentId
1 Power Supply NULL
2 Fan 1
4 Heat Tape 1
3 Screw 2
我有一个分层数据库,我想从中 return 具有 特定 公共父组件的资产中的所有组件。
tableastComponents
中的组件通过 ParentComponentId
链接到它们的父组件,引用其他组件的 Id
。然而,这只显示父级上一级。
此外,所有组件都通过 AssetId
键链接到资产,链接到 table astAssets
.
Id
键
我能够进行一个简单的查询(如下)来检索特定资产的所有组件。我不知道如何 return 来自共享相同父组件的特定资产的所有组件。此父组件可能(相对于子组件)1 到多个级别。
Select C.Id, C.Code, ParentC.Id, ParentC.Code, A.Code
From astComponents C
Join astAssets A ON A.Id = C.AssetId
Join astComponents ParentC ON ParentC.Id = C.ParentComponentId
Where A.Code = '2018100000'
以上查询 return 的组件及其上一级的父组件。如果我指定父代码,它只会 return 子组件比这个指定组件低一级,而不是所有级别。
所以如果我没有理解错的话,你有一个已知的父组件,和一个已知的资产代码。使用它们,您想构建一个树,覆盖从父组件到相关资产的 路径 (缺少更好的词)?
这是一个尝试。我们首先构建一些用于测试的虚拟数据:
declare @component table (
id int primary key,
code nvarchar(50) not null,
parent_id int null,
asset_id int null
)
declare @asset table (
id int primary key,
code nvarchar(50)
)
insert into @asset values (1, '2018100000')
insert into @asset values (2, '2019100000')
insert into @component values(1, 'root', null, null)
insert into @component values(2, 'c1', 1, null)
insert into @component values(3, 'c2', 1, null)
insert into @component values(4, 'c3', 1, null)
insert into @component values(5, 'c2_c1', 3, null)
insert into @component values(6, 'c2_c2', 3, 1)
insert into @component values(7, 'c2_c1_c1', 5, 2)
insert into @component values(8, 'c2_c1_c2', 5, 1)
insert into @component values(9, 'c2_c1_c2_c1', 8, 2)
insert into @component values(9, 'c2_c1_c1_c1', 7, 1)
然后我们声明几个递归 CTE
:s 并使用它们来获取输出:
declare @specParentId int
declare @assetCode nvarchar(50)
set @specParentId = 3
set @assetCode = '2018100000'
;with compRecurseDown as (
select c.id, c.code, parent_id, 0 as level, c.asset_id
from @component c
where c.id = @specParentId
union all
select c.id, c.code, c.parent_id, p.level + 1, c.asset_id
from @component c
join compRecurseDown p on c.parent_id = p.id
), assetRecurseUp as (
select c.*
from @asset a
join @component c on a.id = c.asset_id
where a.code = @assetCode
union all
select c.*
from @component c
join assetRecurseUp p on p.parent_id = c.id
)
select crd.*, a.code as asset_code
from compRecurseDown crd
left outer join @asset a on crd.asset_id = a.id
where crd.id in (
select id from assetRecurseUp
)
order by level
在这种情况下,我们要在 ID 为 3
的组件下查找资产 2018100000
。结果:
| id | code | parent_id | level | asset_id | asset_code |
|----|----------|-----------|-------|----------|------------|
| 3 | c2 | 1 | 0 | NULL | NULL |
| 5 | c2_c1 | 3 | 1 | NULL | NULL |
| 6 | c2_c2 | 3 | 1 | 1 | 2018100000 |
| 8 | c2_c1_c2 | 5 | 2 | 1 | 2018100000 |
那么这是如何工作的呢?首先我们声明 compRecurseDown
CTE。它使用已知的父组件作为其anchor
,然后递归查找该节点下的所有子注释。
assetRecurseUp
CTE 首先查找所有链接到已知资产的组件。然后它基于此递归添加所有父节点。
最后我们查询这两者的组合,产生最终的结果集。
好的,没有任何数据可以使用,这里有很多猜测。我创建了一些数据:
DECLARE @astComponents TABLE (Id INT, Code VARCHAR(50), ParentComponentId INT, AssetId INT);
DECLARE @astAssets TABLE (Id INT, Code VARCHAR(50));
INSERT INTO @astAssets SELECT 1, '2018100000';
INSERT INTO @astAssets SELECT 2, '2018100001';
INSERT INTO @astComponents SELECT 1, 'Power Supply', NULL, 1;
INSERT INTO @astComponents SELECT 2, 'Fan', 1, NULL;
INSERT INTO @astComponents SELECT 3, 'Screw', 2, NULL;
INSERT INTO @astComponents SELECT 4, 'Heat Tape', 1, NULL;
INSERT INTO @astComponents SELECT 5, 'Magnet', NULL, 2;
INSERT INTO @astComponents SELECT 6, 'Iron', 5, NULL;
你可以用这个做的是使用递归映射出所有共享一个公共父级的组件,并记录它们属于哪个资产,例如:
--Make a recursive list of components sharing a common parent
WITH cte AS (
SELECT
Id,
ParentComponentId,
AssetId
FROM
@astComponents
WHERE
ParentComponentId IS NULL
UNION ALL
SELECT
c.Id,
c.ParentComponentId,
cte.AssetId
FROM
@astComponents c
INNER JOIN cte ON cte.Id = c.ParentComponentId)
SELECT * FROM cte;
我打赌你的桌子不是这样工作的,所以你需要调整它以适应。就我而言,我得到以下结果:
Id ParentComponentId AssetId
1 NULL 1
5 NULL 2
6 5 2
2 1 1
4 1 1
3 2 1
所以我可以看到组件 #1 和 #5 没有父组件,所以这些是 "top level" 个组件,我还可以看到哪些组件 link 属于哪些资产。
现在只需将查询的 SELECT * FROM cte
部分替换为如下内容即可:
SELECT
cte.Id,
c.Code,
c.ParentComponentId
FROM
cte
INNER JOIN @astComponents c ON c.Id = cte.Id
INNER JOIN @astAssets a ON a.Id = cte.AssetId
WHERE
a.Code = '2018100000';
给我共享一个父项的所有组件,其中父项的资产代码为 201810000:
Id Code ParentComponentId
1 Power Supply NULL
2 Fan 1
4 Heat Tape 1
3 Screw 2