我有一个分层数据库,我想从中返回具有特定通用父组件的资产中的所有组件。
表astComponents
中的组件通过引用其他组件ParentComponentId
的{{1}}链接到其父组件。但是,这仅将父级显示一级。
此外,所有组件都通过Id
键链接到资产,并链接到表AssetId
中的Id
键。
我能够进行一个简单的查询(如下),以从特定资产中检索所有组件。我无法弄清楚如何从共享同一父组件的特定资产中返回所有组件。此父级组件(相对于子级组件)可以向上一级升级。
astAssets
上面的查询将组件及其父级返回一级。如果我指定父代码,它将仅将子组件返回到此指定组件下一级的子组件,而不是返回所有下一级的子组件。
答案 0 :(得分:1)
好的,没有任何可用的数据,这里有很多猜测。我创建了一些数据:
ComboBox
您可以执行以下操作:使用递归来映射共享同一父级的所有组件,并记录它们属于哪个资产,例如:
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;
因此,我可以看到组件#1和#5没有父级,因此它们是“顶级”组件,并且我还可以看到哪些组件链接到哪些资产。
现在仅是将查询的Id ParentComponentId AssetId
1 NULL 1
5 NULL 2
6 5 2
2 1 1
4 1 1
3 2 1
部分替换为这样的情况:
SELECT * FROM cte
为我提供了共享父级的所有组件,其中父级的资产代码为201810000:
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';
答案 1 :(得分:0)
因此,如果我正确理解了这一点,则您有一个已知的父组件,和一个已知的资产代码。您想使用它们来构建一棵树,覆盖从父级组件到所讨论资产的路径(由于缺少更好的词)?
这是一种尝试。我们首先构建一些用于测试的伪数据:
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为2018100000
的组件下寻找资产3
。结果:
| 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首先找到链接到已知资产的所有组件。然后,基于此递归添加所有父节点。
最后,我们查询这两者的组合以产生最终结果集。