申请:这是一个物料清单系统,其中儿童成分成本(或“在制品”)乘以每个孩子的父母使用因子。
目标:使用自下而上的递归,使用表tblLINK中的Parent / Child和UseRate更新表tblITEM上的成本。 tblITEM有记录类型(C =原材料,P =正在进行中,N =成品)。
状态:它一次成功更新了一行,但它需要运行存储过程22次(完全爆炸级别)。在搞砸之后,它甚至都破了。任何方向都会非常感激,我对tsql有一个粗略的了解。
环境:它将作为我从Access 2013调用的存储过程在SQL Server 2012上运行。
编辑:更新了代码注释并提供了预期更新的可视化显示。
在此结束
Parent 219558 <== Update Item record with Sum Of Factored Consumes ($11,790.00)
--------------
Consumes 218158 @ UseRate 2.0 * Cost $5,895.00 = $11,790.00
Parent 218158 <== Update Item record with Sum Of Factored Consumes ($5,895.00)
--------------
Consumes 219358 @ UseRate 2.5 * Cost $2,358.00 = $ 5,895.00
Parent 219358 <== Update Item record with Sum Of Factored Consumes ($2,358.00)
--------------
Consumes 115132 @ UseRate 3.0 * Cost $ 786.00 = $ 2,358.00
Parent 115132 <== Update Item record with Sum Of Factored Consumes ($786.00)
--------------
Consumes 110506 @ UseRate 1.5 * Cost $ 524.00 = $ 786.00
Parent 110506 <== Update Item record with Sum Of Factored Consumes ($524.00)
--------------
Consumes 109 @ UseRate 0.5 * Cost $1,000.00 = $ 500.00
Consumes 4173 @ UseRate 2.0 * Cost $ 6.00 = $ 12.00
Consumes 4803 @ UseRate 2.0 * Cost $ 6.00 = $ 12.00
从这里开始
向上翻阅树,总结因果结果并更新tblITEM上的父记录
发生的是底部的109价格上涨,我希望通过父母来提高成本并更新表格tblITEM。
USE [BOM_LINK_TEST]
GO
-- Drop tables if they already exist
IF OBJECT_ID('dbo.tblITEM', 'U') IS NOT NULL
DROP TABLE dbo.tblITEM;
IF OBJECT_ID('dbo.tblLINK', 'U') IS NOT NULL
DROP TABLE dbo.tblLINK;
------------------- BEGIN DDLs -------------------------
---------------------------------------------------------
--Create tblITEM Table
CREATE TABLE [dbo].[tblITEM](
[ItemID] [nvarchar](15) NOT NULL,
[ItemType] char(1) NOT NULL,
[RMCost] [numeric](18,6) NULL,
[OHCost] [numeric](18,6) NULL,
[TotalCost] [numeric](18,6) NULL,
CONSTRAINT [PK_tblITEM] PRIMARY KEY CLUSTERED
(
[ITEMID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
--Update tblITEM with Data
INSERT INTO tblITEM ( ItemID, ItemType, RMCost, OHCost, TotalCost )
VALUES
(109, 'C', 1000.00, 0.003501, 0.503501)
,(110506, 'P', 2.50, 0.004206, 2.504206)
,(115132, 'P', 4.58, 0.002409, 4.582409)
,(4803, 'C', 6.00, 0.004509, 9.582409)
,(219358, 'P', 9.45, 1.000504, 10.450504)
,(4173, 'C', 6.00, 0.004509, 9.582409)
,(218158, 'P', 12.00, 1.450105, 13.450105)
,(219558, 'N', 13.67, 1.004504, 14.674504)
;
--Create tblLINK Table
CREATE TABLE [dbo].[tblLINK](
[ParentItem] [nvarchar](15) NOT NULL,
[ChildItem] [nvarchar](15) NOT NULL,
[UseFactor] [numeric](20, 6) NULL,
CONSTRAINT [PK_tblLINK] PRIMARY KEY CLUSTERED
(
[ParentItem] ASC,
[ChildItem] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
--Update tblLINK with Data
INSERT INTO tblLINK( ParentItem, ChildItem, UseFactor )
VALUES
(110506, 109, 0.5000)
,(110506, 4173, 2.0000)
,(115132, 110506, 1.5000)
,(219358, 115132, 3.0000)
,(110506, 4803, 2.0000)
,(218158, 219358, 2.5000)
,(219558, 218158, 2.0000)
;
---***** THIS IS THE PORTION THAT DOES NOT WORK PROPERLY *****---
-- It performs the recursion, but does not recursively update
------------------- Start ROLL-UP RECALC -----------------------
-----------------------------------------------------------------
;With
--Bottom-Up Anchor
cteTREE AS
(
SELECT
p.ChildItem,
p.ParentItem,
p.UseFactor
FROM tblLINK p
UNION ALL
SELECT
c.ChildItem,
c.ParentItem,
c.UseFactor
FROM tblLINK c
-- Invert Join To Walk Up Tree
INNER JOIN cteTREE p ON c.ChildItem = p.ParentItem
),
-- Sum of Children
cSUM AS
(
SELECT BL.ParentItem,
CAST(Sum(BI.RMCost * BL.UseFactor) AS numeric(18,6)) AS SumRMCost,
CAST(Sum(BI.OHCost * BL.UseFactor) AS numeric(18,6)) AS SumOHCost,
CAST(Sum(BI.RMCost * BL.UseFactor) AS numeric(18,6)) +
CAST(Sum(BI.OHCost * BL.UseFactor) AS numeric(18,6)) AS SumTotalCost
FROM tblLINK as BL
INNER JOIN tblITEM as BI
ON BL.ParentItem = BI.ItemID
GROUP BY ParentItem
)
--******** This Update is where I have an issue ********** ----
-- The Update Statement was only updating one row at a time
-- I believe a different join, output, rollup, level, hierarchyID
-- or temp table is needed to sum the children first
-- so that the update sequentially rolls all the way up the tree
-- Perform Table Updates With Summed Result Set
UPDATE tblITEM
SET
RMCost = cSUM.SumRMCost,
OHCost = cSUM.SumOHCost,
TotalCost = cSUM.SumTotalCost
FROM cSUM
INNER JOIN tblITEM AS tBI
ON cSUM.ParentItem = tBI.ItemID
---------------------- Show Results -----------------------------------
------------------------------------------------------------------------
SELECT TOP 1000 [ItemID]
,[ItemType]
,[RMCost]
,[OHCost]
,[TotalCost]
FROM [BOM_LINK_TEST].[dbo].[tblITEM]