Dav*_*vid 6 sql-server query recursive
我很感激我正在努力实现的一些帮助。
我公司制造的零件是由子组件和子组件的子组件构建的。这看起来像:
1
/ \ \
/ | \
2 3 7
/ \ / \
4 5 4 6
Run Code Online (Sandbox Code Playgroud)
4 和 5 组合成 2,4 和 6 组成 3,然后组件 2、3 和 7 组成 1。
我的桌子看起来像这样;
+------+-----+-------+----------+----------------+
| ROOT | SUB | LEVEL | LEADTIME | TOP LEVEL PART |
+------+-----+-------+----------+----------------+
| 1 | 1 | 0 | 4 | 1 |
| 1 | 2 | 1 | 2 | 1 |
| 1 | 3 | 1 | 5 | 1 |
| 1 | 7 | 1 | 20 | 1 |
| 2 | 4 | 1 | 4 | 1 |
| 2 | 5 | 1 | 1 | 1 |
| 3 | 4 | 2 | 4 | 1 |
| 3 | 6 | 2 | 5 | 1 |
+------+-----+-------+----------+----------------+
Run Code Online (Sandbox Code Playgroud)
每个零件都有制作它需要多长时间的提前期。我想要做的是传递顶级零件编号,并计算零件的总体交货时间。
最初我以为我可以按级别分组,然后将每个级别的最大前置时间加在一起,但这并不准确。Level 1 Part 7 制作需要 20 天,所以我们可以在制作 7 的同时制作所有其他部分。计算需要基于消耗其父级的部分(因为需要更好的短语)。
我需要做的是计算通过树的每条路线的提前期,并在进行时将提前期相加。所以我想返回一个类似的表;
+----+----------------+-------------------------+------+------------+
| ID | Top Level Part | Parts Nodes Combination | Days | [BASED ON] |
+----+----------------+-------------------------+------+------------+
| 1 | 1 | 1 >> 2 >> 4 | 10 | 4 + 2 + 4 |
| 2 | 1 | 1 >> 2 >> 5 | 7 | 4 + 2 + 1 |
| 3 | 1 | 1 >> 3 >> 4 | 13 | 4 + 5 + 4 |
| 4 | 1 | 1 >> 3 >> 6 | 14 | 4 + 5 + 5 |
| 5 | 1 | 1 >> 7 | 24 | 4 + 20 |
+----+----------------+-------------------------+------+------------+
Run Code Online (Sandbox Code Playgroud)
然后我可以找到天数列的 MAX,它会告诉我第 1 部分的总交付时间是 24 天。
I really hope I've made my post understandable and all is formatted correctly. I've tried to read up on recursive SQL queries but I'm struggling to get my head around them. The most number of levels I am ever likely to have is 4 so I'd hope it wouldn't be too pc intensive. If so, I'd much rather be able pass all of my parts through, rather than doing them one part at a time (hence why I've got a top level part column in my table).
Any help or advice would be greatly appreciated.
该解决方案还获得了中间节点
;WITH RecursiveCTE
AS
(
SELECT [SUB] ,
[SUB] as [Top Level Part],
CAST([SUB] as varchar(255)) as [Parts Nodes Combination],
0 AS [LEVEL],
[LEADTIME] as [Days],
CAST([LEADTIME] as varchar(255)) as [BASED ON]
FROM dbo.Levels s1
WHERE [LEVEL] = 0
UNION ALL
SELECT s1.SUB as [Top Level Part],
RecursiveCTE.[Top Level Part],
CAST(RecursiveCTE.[Parts Nodes Combination]+ ' >> ' + cast(s1.[SUB] as varchar(255)) as varchar(255)),
RecursiveCTE.[LEVEL] + 1 as [LEVEL],
RecursiveCTE.[Days] + s1.[LEADTIME] as [Days],
CAST(RecursiveCTE.[BASED ON] + ' + ' + CAST(s1.[LEADTIME] as varchar(255)) as varchar(255))
FROM dbo.Levels s1
INNER JOIN RecursiveCTE
ON s1.[ROOT] = RecursiveCTE.[SUB]
WHERE s1.[LEVEL] > 0
)
SELECT * FROM RecursiveCTE
WHERE [LEVEL] != 0;
Run Code Online (Sandbox Code Playgroud)
结果
SUB Top Level Part Parts Nodes Combination LEVEL Days BASED ON
2 1 1 >> 2 1 6 4 + 2
3 1 1 >> 3 1 9 4 + 5
7 1 1 >> 7 1 24 4 + 20
4 1 1 >> 3 >> 4 2 13 4 + 5 + 4
6 1 1 >> 3 >> 6 2 14 4 + 5 + 5
4 1 1 >> 2 >> 4 2 10 4 + 2 + 4
5 1 1 >> 2 >> 5 2 7 4 + 2 + 1
Run Code Online (Sandbox Code Playgroud)
如果要过滤掉中间节点:
;WITH RecursiveCTE
AS
(
SELECT [SUB] ,
[SUB] as [Top Level Part],
CAST([SUB] as varchar(255)) as [Parts Nodes Combination],
0 AS [LEVEL],
[LEADTIME] as [Days],
CAST([LEADTIME] as varchar(255)) as [BASED ON]
FROM dbo.Levels s1
WHERE [LEVEL] = 0
UNION ALL
SELECT s1.SUB as [Top Level Part],
RecursiveCTE.[Top Level Part],
CAST(RecursiveCTE.[Parts Nodes Combination]+ ' >> ' + cast(s1.[SUB] as varchar(255)) as varchar(255)),
RecursiveCTE.[LEVEL] + 1 as [LEVEL],
RecursiveCTE.[Days] + s1.[LEADTIME] as [Days],
CAST(RecursiveCTE.[BASED ON] + ' + ' + CAST(s1.[LEADTIME] as varchar(255)) as varchar(255))
FROM dbo.Levels s1
INNER JOIN RecursiveCTE
ON s1.[ROOT] = RecursiveCTE.[SUB]
WHERE s1.[LEVEL] > 0
)
SELECT * FROM RecursiveCTE
WHERE [LEVEL] != 0
AND NOT EXISTS
(
SELECT * FROM
dbo.Levels s2
WHERE RecursiveCTE.SUB = s2.[ROOT])
;
Run Code Online (Sandbox Code Playgroud)
结果
SUB Top Level Part Parts Nodes Combination LEVEL Days BASED ON
7 1 1 >> 7 1 24 4 + 20
4 1 1 >> 3 >> 4 2 13 4 + 5 + 4
6 1 1 >> 3 >> 6 2 14 4 + 5 + 5
4 1 1 >> 2 >> 4 2 10 4 + 2 + 4
5 1 1 >> 2 >> 5 2 7 4 + 2 + 1
Run Code Online (Sandbox Code Playgroud)
使用的表格和数据
CREATE TABLE dbo.Levels ([PARTID] INT,[ROOT] int,[SUB] int,[LEVEL] int, [LEADTIME] int,[TOP LEVEL PART] int);
--PartID added
INSERT INTO dbo.Levels
([PARTID], [ROOT] ,[SUB] ,[LEVEL] , [LEADTIME] ,[TOP LEVEL PART])
VALUES
(1,1 , 1 ,0 ,4 ,1 ),
(1,1 , 2 ,1 ,2 ,1 ),
(1,1 , 3 ,1 ,5 ,1 ),
(1,1 , 7 ,1 ,20 ,1 ),
(1,2 , 4 ,1 ,4 ,1 ),
(1,2 , 5 ,1 ,1 ,1 ),
(1,3 , 4 ,2 ,4 ,1 ),
(1,3 , 6 ,2 ,5 ,1 );
Run Code Online (Sandbox Code Playgroud)
编辑
操作评论:
我注意到数据重复很多(特别是在较大的装配体上)
基本上,我在顶级路由器 1731 上有子路由器 1691。零件节点组合是 1731 - 1727 - 1691,这会重复完全相同的列 8 次。然后,当它引入另一个节点(例如 1731 - 1727 - 1691 - 1682)时,这个节点会重复 168 次。自始至终都是如此。看起来任何 3 个级别节点重复 8 次,任何 4 个级别节点重复 168 次。
在另一台上,它重复的次数要少得多。我想知道这是否与树中独特部分的数量有关。
我想我已经明白了!单个子可以出现在几个不同的顶级部分上。在连接到 recursiveCTE 表时,我还添加了“and RecursiveCTE.[Top Level Part] = s1.TopLevelRouter”,我认为它已经完成了。
需要更改的部分查询:
...
FROM dbo.Levels s1
INNER JOIN RecursiveCTE
ON s1.[ROOT] = RecursiveCTE.[SUB]
and RecursiveCTE.[Top Level Part] = s1.TopLevelRouter
WHERE s1.[LEVEL] > 0
)
SELECT * FROM RecursiveCTE
WHERE [LEVEL] != 0;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
190 次 |
最近记录: |