2015-05-14 126 views
1

我想要做的只是從物料清單表(物料清單)中獲取相關組件/產品,然後從BOMVERSION中獲取相關組件/產品將其相關組件和產品等降至7個級別。然後,我想轉動結果,以便將相關項目放入列0, 1, 2, 3, 4, 5, 6, 7SQL遞歸CTE'在哪裏'/ BOM爆炸

請參閱附加示例數據和代碼。我正在使用Dynamics AX 2012 R2,但此示例可應用於使用材料/產品的任何系統。然而,我無法完成我的查詢(我知道我沒有dataareaid和分區,爲了簡單起見我省略了)。關係是來自BOM表的itemid與BOMVERSION到BOMID中的itemid有關。

更新:我簡化了數據等,使盡可能簡單/清晰,因此木材,金屬,玻璃材料本身可以用於製造各種產品和材料,並可以組合製造產品或材料。因此,我想從一個基礎組件開始,然後按級別分解關係。

DDL + DML:

USE tempdb; 

IF OBJECT_ID('tempdb..#BOM') IS NOT NULL 
    DROP TABLE #BOM; 

CREATE TABLE #BOM 
    (
     ITEMID NVARCHAR(10) , 
     BOMID NVARCHAR(10) , 
     MATERIALNAME NVARCHAR(10) 
    ); 

INSERT INTO #BOM 
VALUES (N'113621', -- ITEMID - nvarchar(10) 
      N'1', -- BOMID - nvarchar(10) 
      N'Wood' -- MATERIALNAME - nvarchar(10) 
     ); 

INSERT INTO #BOM 
VALUES (N'234517', -- ITEMID - nvarchar(10) 
      N'2', -- BOMID - nvarchar(10) 
      N'Metal' -- MATERIALNAME - nvarchar(10) 
     ); 

INSERT INTO #BOM 
VALUES (N'378654', -- ITEMID - nvarchar(10) 
      N'3', -- BOMID - nvarchar(10) 
      N'Glass' -- MATERIALNAME - nvarchar(10) 
     ); 

IF OBJECT_ID('tempdb..#BOMVERSION') IS NOT NULL 
    DROP TABLE #BOMVERSION; 

CREATE TABLE #BOMVERSION 
    (
     ITEMID NVARCHAR(10) , 
     BOMID NVARCHAR(10) , 
     NAME NVARCHAR(20) 
    ); 

INSERT INTO #BOMVERSION 
VALUES (N'113477', -- ITEMID - nvarchar(10) 
      N'1', -- BOMID - nvarchar(10) 
      N'Oak' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113608', -- ITEMID - nvarchar(10) 
      N'1', -- BOMID - nvarchar(10) 
      N'Pine' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113622', -- ITEMID - nvarchar(10) 
      N'1', -- BOMID - nvarchar(10) 
      N'Wood Table' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113683', -- ITEMID - nvarchar(10) 
      N'2', -- BOMID - nvarchar(10) 
      N'Aluminium' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113689', -- ITEMID - nvarchar(10) 
      N'2', -- BOMID - nvarchar(10) 
      N'Steel' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113693', -- ITEMID - nvarchar(10) 
      N'2', -- BOMID - nvarchar(10) 
      N'Metal table' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113694', -- ITEMID - nvarchar(10) 
      N'3', -- BOMID - nvarchar(10) 
      N'Glass' -- NAME - nvarchar(10) 
     ); 

INSERT INTO #BOMVERSION 
VALUES (N'113695', -- ITEMID - nvarchar(10) 
      N'3', -- BOMID - nvarchar(10) 
      N'Glass BookCase' -- NAME - nvarchar(10) 
     ); 

--Query 

WITH BOM1 
      AS (SELECT B.ITEMID AS BITEMID , 
         BV.ITEMID AS BVITEMID , 
         B.MATERIALNAME , 
         B.BOMID 
       FROM  #BOM AS B 
         JOIN #BOMVERSION AS BV ON BV.BOMID = B.BOMID 
      ), 
     EXPLODE 
      AS (SELECT B.BITEMID , 
         B.MATERIALNAME , 
         B.BVITEMID , 
         B.BOMID , 
         0 AS [Level] 
       FROM  BOM1 AS B 
       UNION ALL 
       SELECT B.BITEMID , 
         E.MATERIALNAME , 
         E.BVITEMID , 
         E.BOMID , 
         [E].[Level] + 1 
       FROM  EXPLODE AS E 
         JOIN BOM1 AS B ON B.BOMID = E.BOMID 
       WHERE E.Level <= 6 --narrowing levels     
      ) 
    SELECT * 
    FROM EXPLODE PIVOT (MAX(BVITEMID) FOR Level IN ([0], [1], [2], [3], 
                 [4], [5], [6], [7])) AS PVTBOM; 

輸出看起來像enter image description here

+0

那麼,你得到+1包括DDL + DML的樣本數據,但因爲-1它不清楚你是什麼問。 –

+0

嗨,我不知道如何讓它更清晰...獲得一件物品,通過bomid獲取相關物品,獲取相關物品到該物品等等等級按等級轉動 – jhowe

回答

2

嗯,這只是爲了消除錯誤,並得到結果,但我不知道,如果結果是正確的:

WITH BOM1 
      AS (SELECT B.ITEMID AS BITEMID , 
         BV.ITEMID AS BVITEMID , 
         B.BOMID 
       FROM  #BOM AS B 
         JOIN #BOMVERSION AS BV ON BV.BOMID = B.BOMID 
      ), 
     EXPLODE 
      AS (SELECT B.BITEMID , 
         B.BVITEMID , 
         B.BOMID , 
         0 AS [Level] 
       FROM  BOM1 AS B 
       UNION ALL 
       SELECT B.BITEMID , 
         E.BVITEMID , 
         E.BOMID , 
         [E].[Level] + 1 
       FROM  EXPLODE AS E 
         JOIN BOM1 AS B ON B.BOMID = E.BOMID 
       WHERE e.Level <= 6 --narrowing levels     
      ) 


    SELECT * 
    FROM EXPLODE PIVOT (MAX(BVITEMID) FOR Level IN ([0], [1], [2], [3], 
                 [4], [5], [6], [7])) AS PVTBOM 

你有maxrecursion = 7 - 這不是縮小關卡的地方。在CTE的遞歸部分中縮小級別。

我懷疑你的遞歸組織不好,你能簡化你的測試數據嗎?只留下幾行並顯示預期的輸出。

EDIT1:

WITH p AS (SELECT * 
       FROM  (SELECT itemid , 
            bomid , 
            ROW_NUMBER() OVER (PARTITION BY Bomid ORDER BY itemid) rn 
          FROM  #BOMVERSION 
         ) t PIVOT (MAX(itemid) FOR rn IN ([1], [2], [3], [4], 
                  [5], [6], [7], [8])) p 
      ) 
    SELECT * 
    FROM #bom b 
JOIN p ON b.bomid = p.bomid  

EDIT2:

;WITH cte 
      AS (SELECT b.itemid AS originalitem , 
         b.bomid AS originalbom , 
         b.bomid , 
         bv.itemid AS parent , 
         0 AS level 
       FROM  #BOM b 
         JOIN #BOMVERSION bv ON bv.bomid = b.bomid 
       UNION ALL 
       SELECT c.originalitem , 
         c.originalbom , 
         b.bomid , 
         bv.itemid , 
         c.level + 1 
       FROM  cte c 
         JOIN #BOM b ON c.parent = b.itemid 
         JOIN #BOMVERSION bv ON bv.bomid = b.bomid 
       WHERE c.level <= 6 
      ), 
     tree 
      AS (SELECT originalitem , 
         originalbom , 
         parent , 
         level 
       FROM  cte 
      ) 
    SELECT * 
    FROM tree PIVOT (MAX(parent) FOR level IN ([0], [1], [2], [3], [4], [5], [6], [7])) AS p 
+0

感謝加入等級限制是一個很大的幫助,我至少可以讓查詢現在正常運行。讓我看看具有適當數據的這個樣子......很快會得到反饋。 – jhowe

+0

嗨,我已經更新並試圖儘可能簡化。我只是試圖展示這些項目之間的關係,所以伍德製作了一張木桌,並進入了松樹和橡樹等玻璃進入製造玻璃書櫃,木材也進入它,這種事情...... – jhowe

+1

@ jhowe,這裏不需要遞歸cte。看編輯。 –