2015-05-14 4 views
1

То, что я пытаюсь сделать просто, - это элемент из таблицы спецификации (спецификации), который получает связанные компоненты/продукты от BOMVERSION, а затем для этих связанных компонентов/продукты получают свои связанные компоненты и продукты и т. д. до 7 уровней. Затем я хочу изменить результаты, чтобы связанные элементы попадали в столбцы 0, 1, 2, 3, 4, 5, 6, 7SQL Рекурсивный CTE «где-используется»/взрыв BOM

См. Приведенные примеры данных и кода. Я использую динамику AX 2012 R2, но этот пример можно применить к любой системе, которая использует материалы/продукты. Однако я не могу получить свой запрос (я знаю, что у меня нет данных и разделов, которые я забыл для простоты). это отношение itemid из таблицы BOM относится к itemid в BOMVERSION через BOMID.

ОБНОВЛЕНИЕ: У меня есть упрощенные данные и т. Д., Чтобы сделать их как можно более простыми/ясными, поэтому материалы из дерева, металла, стекла могут входить в различные продукты и материалы и могут быть объединены для изготовления изделий или материалов. Поэтому я хочу начать с базового компонента, а затем разложить отношения по уровням.

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, нет необходимости в рекурсивном ците здесь. Посмотрите на редактирование. –

Смежные вопросы