递归CTE - 从底部到顶部更新成本 - SQL Server

时间:2016-10-03 16:55:27

标签: sql-server recursion

申请:这是一个物料清单系统,其中儿童成分成本(或“在制品”)乘以每个孩子的父母使用因子。

目标:使用自下而上的递归,使用表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]

0 个答案:

没有答案