Jef*_*der 5 join sql-server cte cross-apply
我有三个相关的表:Parts、PartGroup 和 MarkupGroup。
零件很简单。
PartID artificial primary key
Part part number
PartGroupID Foreign key
Run Code Online (Sandbox Code Playgroud)
样本数据:
1 T1000 5
2 wizbang gold 17
3 flux capacitor 2
Run Code Online (Sandbox Code Playgroud)
PartGroup 是一个使用自链接父键建模的无环有向图(树)
PartGroupID artificial primary key
Description name of group
ParentID foreign key linked to PartGroupID
MarkupGroupID foreign key linked to MarkupGroup
Run Code Online (Sandbox Code Playgroud)
示例数据如下所示 -
1 system null null
2 component null 1
3 software null 2
4 abc 1 3
5 xyz 1 4
6 123 4 null
7 456 4 null
8 789 5 null
9 a1 6 null
10 b2 6 null
11 c3 7 null
12 d4 7 null
13 e5 8 null
14 f6 8 null
15 alpha 3 null
16 beta 3 null
17 gamma 3 null
Run Code Online (Sandbox Code Playgroud)
MarkupGroup 是将一个标记因子作为一个集合应用于多个 PartGroup。
MarkupGroupID primary key
MarkupFactor numeric attribute field
Run Code Online (Sandbox Code Playgroud)
样本数据-
1 15
2 20
3 25
4 22
Run Code Online (Sandbox Code Playgroud)
我需要编写一个查询,为部件表中的每个部件返回适当的标记量。永远不会有多个标记可以应用于一个零件的情况。我需要递归图形以找到标记,并且在查询时我不知道需要递归多少级才能找到非空标记。
永远不会出现部件在向上树的过程中遇到多个可能连接到边距的情况,因此不需要进行累积。
t1000 是 xyz 类型,它有一个 MarginGroup 的外键,所以我们可以加入并获得一个值。它也有一个父对象,但这无关紧要,因为我们拥有所需的值。
Wizbang Gold 是伽马组软件,它没有外键,但父节点“软件”有,我们应该返回它。
磁通电容器是一个组件,它有一个指向 MarginGroup 的直接外键。返回那个值。
所以结果将是:
1 T1000 22
2 wizbang gold 20
3 flux capacitor 15
Run Code Online (Sandbox Code Playgroud)
我很确定我需要一个递归 CTE 和一些 APPLY 来得到这个,但我的大脑目前不太好。如果不是因为中间表的递归性质,这将非常简单。平台是 MS-SQL。
您可以随身携带从上到下在 CTE 中进行递归MarkupGroupID
。
with C as
(
select P.PartGroupID,
P.ParentID,
P.MarkupGroupID
from PartGroup as P
where P.ParentID is null
union all
select P.PartGroupID,
P.ParentID,
coalesce(P.MarkupGroupID, C.MarkupGroupID)
from PartGroup as P
inner join C
on P.ParentID = C.PartGroupID
)
select P.PartID,
P.Part,
MG.MarkupFactor
from Parts as P
inner join C
on P.PartGroupID = C.PartGroupID
inner join MarkupGroup as MG
on C.MarkupGroupID = MG.MarkupGroupID
order by P.PartID
Run Code Online (Sandbox Code Playgroud)
递归 CTE 将创建一个如下所示的派生表。
PartGroupID ParentID MarkupGroupID
----------- ----------- -------------
1 NULL NULL
2 NULL 1
3 NULL 2
15 3 2
16 3 2
17 3 2
4 1 3
5 1 4
8 5 4
13 8 4
14 8 4
6 4 3
7 4 3
11 7 3
12 7 3
9 6 3
10 6 3
Run Code Online (Sandbox Code Playgroud)
如果您需要零件组未连接到标记的零件,您可以MarkupGroup
在主查询中使用外连接。
with C as
(
select ...
)
select P.PartID,
P.Part,
MG.MarkupFactor
from Parts as P
inner join C
on P.PartGroupID = C.PartGroupID
left outer join MarkupGroup as MG
on C.MarkupGroupID = MG.MarkupGroupID
order by P.PartID
Run Code Online (Sandbox Code Playgroud)