我有物料清单(bom)。让我们称之为BOM 301755。
BOM 301755由这些部分组成
31161201 = need 1 pc of this
29975413 = need 2 pcs of this
299756 = need 2 pcs of this
And 305958 = need 1 pc of this
这将是零级。
现在让我们关注其中一个部分。部分:29975413。 第29975413部分由:
组成PLTSSL902 = 1pc
CAPSSL902 = 1pc
PIPSSL4SCH40 = 3.96
And LABSTR = 0.166
现在我们需要2台29975413。 我该如何进行查询,以便显示如下:
PLTSSL902 = 1pc x 2 = 2 pc
CAPSSL902 = 1pc x 2 = 2 pc
PIPSSL4SCH40 = 3.96 x 2 = 7.92
And LABSTR = 0.166 x 2 = 0.332
我绘制这个以便于阅读person。 :)
谢谢
答案 0 :(得分:2)
为了使它在应用程序中更加通用,我修改了@ dazedandconfused的答案:
;WITH bom as (
SELECT pid p,cid c, qty q, 0 bomlvl FROM #t WHERE pid='301755' // start id
UNION ALL
SELECT pid, cid, q*qty, bomlvl+1 FROM #t INNER JOIN bom ON c=pid
)
SELECT * from bom a WHERE NOT EXISTS (SELECT 1 FROM bom WHERE p=a.c)
此查询计算每一行的物料清单级别,并且仅列出仅没有子项的物料清单的那些元素,无论您的物料清单可能有多少级别。可以找到一个小提琴here。
我的例子将提供结果:
p c q bomlvl
-------- ------------ ----- ------
305958 311620 4 1
305958 311620 0.1 1
299756 RDBSSL012 0.2 1
299756 RDBSSL012 6.834 1
29975413 PLTSSL902 2 1
29975413 CAPSSL4SCH40 2 1
29975413 PIPSSL4SCH40 7.92 1
29975413 LABSTR 0.332 1
31161201 PIPSSL2SCH40 4 1
您可以更进一步,按照c
- ID对结果进行分组,以获得特定BOM中使用的总金额。表值函数将是编写此函数的最佳方式,其中您将初始Id作为参数传递。我无法在我的data.stackexchange-fiddle中演示这个,因为函数不能引用临时表,但函数定义应该看起来或多或少像这样:
CREATE FUNCTION bomqty ( @pid varchar(20) ) RETURNS TABLE AS BEGIN
;WITH bom as (
SELECT pid p,cid c, qty q, 0 bomlvl FROM tbl WHERE pid=@pid
UNION ALL
SELECT pid, cid, q*qty, bomlvl+1 FROM tbl INNER JOIN bom ON c=pid
)
RETURN SELECT c item,sum(q) totalqty FROM bom a
WHERE NOT EXISTS (SELECT 1 FROM bom WHERE p=a.c)
GROUP BY c
END;
然后可以像使用其他任何表一样使用该函数:
SELECT * FROM bomqty('301755')
这会让你
item totalqty
------------ --------
311620 4.1
CAPSSL4SCH40 2
LABSTR 0.332
PIPSSL2SCH40 4
PIPSSL4SCH40 7.92
PLTSSL902 2
RDBSSL012 7.034
答案 1 :(得分:1)
这样的事情应该有效:
CREATE TABLE #TableBom
(
Bom INT
,KitId INT
,SubAssy VARCHAR(20)
,BomLevel INT
,StdQty DECIMAL(10 ,3)
);
INSERT INTO #TableBom
SELECT 301755, 301755, '29975413', 0, 2
UNION ALL
SELECT 301755, 29975413, 'PLTSSL902', 1, 1
UNION ALL
SELECT 301755, 29975413, 'CAPSSL902', 1, 1
UNION ALL
SELECT 301755, 29975413, 'PIPSSL4SCH40',1,3.96
UNION ALL
SELECT 301755, 29975413, 'LABSTR', 1, 0.166
UNION ALL
SELECT 301755, 299756, 'RDBSSL012', 1, 3.147
SELECT b.Bom
,b2.SubAssy
,CONCAT(b2.SubAssy, ' = ' ,CAST(b2.StdQty AS DECIMAL(10,3)) ,' pc x ' ,CAST(b.StdQty AS DECIMAL(10,3)) ,' = ' ,CAST((b2.StdQty * b.StdQty) AS DECIMAL(10,2)) ,' pc') AS Calc
FROM #TableBom AS b
INNER JOIN #TableBom AS b2 ON b.SubAssy = CAST(b2.KitId AS VARCHAR(20));
Bom SubAssy Calc
301755 PLTSSL902 PLTSSL902 = 1.000 pc x 2.000 = 2.00 pc
301755 CAPSSL902 CAPSSL902 = 1.000 pc x 2.000 = 2.00 pc
301755 PIPSSL4SCH40 PIPSSL4SCH40 = 3.960 pc x 2.000 = 7.92 pc
301755 LABSTR LABSTR = 0.166 pc x 2.000 = 0.33 pc
编辑:
如果您只想包含29975413,则可以添加WHERE b.SubAssy = '29975413'
答案 2 :(得分:1)
您可以使用递归公用表表达式来遍历部分层次结构,传递父项的数量并将子项的数量乘以它。
DECLARE @bom int = 301755
CREATE TABLE #t(
BOM int,
KitID varchar(20),
SubAssy varchar(20),
BOMLevel int,
StdQty float
)
INSERT #t(BOM, KitID, SubAssy, BOMLevel, StdQty) VALUES
(301755, '301755', '31161201', 0, 1),
(301755, '301755', '29975413', 0, 2),
(301755, '301755', '299756', 0, 2),
(301755, '301755', '305958', 0, 1),
(301755, '305958', '311620', 1, 4),
(301755, '305958', '311620', 1, .1),
(301755, '299756', 'RDBSSL012', 1, .1),
(301755, '299756', 'RDBSSL012', 1, 3.417),
(301755, '29975413', 'PLTSSL902', 1, 1),
(301755, '29975413', 'CAPSSL4SCH40', 1, 1),
(301755, '29975413', 'PIPSSL4SCH40', 1, 3.96),
(301755, '29975413', 'LABSTR', 1, .166),
(301755, '31161201', 'PIPSSL2SCH40', 1, 4)
;WITH cte AS (
SELECT KitID, SubAssy, StdQty FROM #t WHERE KitID = @bom
UNION ALL
SELECT #t.KitID, #t.SubAssy, cte.StdQty * #t.StdQty FROM #t
INNER JOIN cte ON cte.SubAssy = #t.KitID
)
SELECT * FROM cte ORDER BY KitID, SubAssy