我有一个BOM表公式表,其中列出了BOM项目及其组件。表有两个字段:BOM和组件字段。组件项可能是另一个公式。例如:
BOM, Component
A1, C1
A1, C2
A1, C3
A2, C4
A2, C5
C2, C6
C2, C7
C7, C8
C7, C9
C7, C10
项目A1具有C1,C2和C3组件。
如何使用SQL列出递归类型查询以查找A1项目的所有原材料?递归级别未知。在这种情况下,A1具有C1,C3,C6,C8,C9和C10原料。
通过以下示例更新问题:
BOM是从组件项目组装的项目。需要查询才能获得物料清单物料的所有原料成分以进行生产物料计划。
A1是BOM项目,由C1,C2和C3组装而成 C2是BOM项目,由C6和C7组装而成 C7是BOM项目,由C8,C9和C10组装而成。
BOM项目A1的组件是C1,C3,C6,C8,C9和C10。 C2和C7是BOM项目,它们不是原材料项目。
输出将是:
A1 C1
A1 C3
A1 C6
A1 C8
A1 C9
A1 C10
A2 C4
A2 C5
以下记录是选项。它可以在输出上,也可以不在输出上。
C2 C6
C2 C8
C2 C9
C2 C10
C7 C8
C7 C9
C7 C10
答案 0 :(得分:2)
已编辑:现在只会显示不属于其他组件的BOM
WITH DirectReports (BOM, Component, Level)
AS
(
-- Anchor member definition
SELECT e.BOM, e.Component, 0 AS Level
FROM dbo.BOM AS e
UNION ALL
-- Recursive member definition
SELECT d.BOM, e.Component, Level + 1
FROM dbo.BOM AS e
INNER JOIN DirectReports AS d
ON e.BOM = d.Component
AND d.Level = Level
)
-- Statement that executes the CTE
SELECT DR.BOM, DR.Component, DR.Level, B.Component
FROM DirectReports DR
LEFT JOIN BOM B
ON DR.BOM = B.Component
WHERE B.Component IS NULL
ORDER BY BOM
GO
<强>输出强>
| BOM | Component | Level | Component |
|-----|-----------|-------|-----------|
| A1 | C1 | 0 | (null) |
| A1 | C2 | 0 | (null) |
| A1 | C3 | 0 | (null) |
| A1 | C6 | 1 | (null) |
| A1 | C7 | 1 | (null) |
| A1 | C8 | 2 | (null) |
| A1 | C9 | 2 | (null) |
| A1 | C10 | 2 | (null) |
| A2 | C4 | 0 | (null) |
| A2 | C5 | 0 | (null) |
答案 1 :(得分:1)
这不会达到任何级别,但这个想法很简单,您可以添加任意数量的级别
DECLARE @tbl TABLE(BOM VARCHAR(10), Component VARCHAR(10));
INSERT INTO @tbl VALUES
('A1','C1')
,('A1','C2')
,('A1','C3')
,('A2','C4')
,('A2','C5')
,('C2','C6')
,('C2','C7')
,('C7','C8')
,('C7','C9')
,('C7','C10');
WITH rCTE AS
(
SELECT tbl.BOM,tbl.Component,1 AS Level
FROM @tbl AS tbl
WHERE NOT EXISTS(SELECT 1 FROM @tbl WHERE Component=tbl.BOM)
UNION ALL
SELECT nxt.BOM,nxt.Component,rCTE.Level+1
FROM rCTE
INNER JOIN @tbl AS nxt ON rCTE.Component=nxt.BOM
)
SELECT lvl1.BOM AS l1
,ISNULL(lvl1.Component,lvl2.BOM) AS l2
,ISNULL(lvl2.Component,lvl3.BOM) AS l3
,ISNULL(lvl3.Component,lvl4.BOM) AS l4
FROM rCTE AS lvl1
LEFt JOIN rCTE AS lvl2 ON lvl1.Component=lvl2.BOM AND lvl2.Level=2
LEFt JOIN rCTE AS lvl3 ON lvl2.Component=lvl3.BOM AND lvl3.Level=3
LEFt JOIN rCTE AS lvl4 ON lvl3.Component=lvl4.BOM AND lvl4.Level=4
WHERE lvl1.Level=1
结果
+----+----+------+------+
| A1 | C1 | NULL | NULL |
+----+----+------+------+
| A1 | C2 | C6 | NULL |
+----+----+------+------+
| A1 | C2 | C7 | C8 |
+----+----+------+------+
| A1 | C2 | C7 | C9 |
+----+----+------+------+
| A1 | C2 | C7 | C10 |
+----+----+------+------+
| A1 | C3 | NULL | NULL |
+----+----+------+------+
| A2 | C4 | NULL | NULL |
+----+----+------+------+
| A2 | C5 | NULL | NULL |
+----+----+------+------+
如果您将最终SELECT
更改为此
SELECT lvl1.BOM AS l1
,COALESCE
(
--add more levels top down
ISNULL(lvl3.Component,lvl4.BOM)
,ISNULL(lvl2.Component,lvl3.BOM)
,ISNULL(lvl1.Component,lvl2.BOM)
) AS Comp
FROM rCTE AS lvl1
LEFt JOIN rCTE AS lvl2 ON lvl1.Component=lvl2.BOM AND lvl2.Level=2
LEFt JOIN rCTE AS lvl3 ON lvl2.Component=lvl3.BOM AND lvl3.Level=3
LEFt JOIN rCTE AS lvl4 ON lvl3.Component=lvl4.BOM AND lvl4.Level=4
--add more levels
WHERE lvl1.Level=1
你会得到这个,这似乎非常接近你需要的东西......
A1 C1
A1 C6
A1 C8
A1 C9
A1 C10
A1 C3
A2 C4
A2 C5