SQL 递归 CTE 'where-used'/BOM 爆炸第 2 部分

标签 sql sql-server recursion dynamics-ax-2012

嗨,这是从另一篇文章继续的,

SQL Recursive CTE 'where-used' / BOM explosion

最初的要求已得到解答,但我意识到我现在还有另一个最终要求。我在“1”之后拥有的数据(即描述等)希望对每个级别重复,以便描述正确地识别正确的父项。我尝试在最终选择中再次添加列,但它只是重复了级别 1 中的项目。如何做到这一点?

* 更新 * 我真的很难让测试数据/查询看起来像我想要的那样。我想让这些项目通过 bomid 相互关联。输出看起来像 img。

BOM和BOMVERSION之间的关系是一个项目在BOM表中有多个BOMID,每个bomID在BOMVERSION中都有对应的记录,通过BOMID您可以从BOMVERSION中获得不同的ITEMID。该 itemID 本身可以存在于具有多个 BOMID 的 BOM 表中。我知道这很令人困惑,并且很难用测试数据来证明。这就是为什么我很高兴获得赏金。

*更新*根据我所了解到的,我已经重做了查询/测试数据。我无法让它完全执行我想要的操作,因此可能需要调整或添加查询/数据。我会输出我所期望的。基本上,当 BOM.ItemID 通过 BOMID 链接到 BV.ItemID 时,我希望 BV.ItemID 移动到下一个级别,然后如果该 BOM.ItemID 链接到另一个 BV.ItemID 则将该项目移动到下一个级别等等。以及与关卡中的项目相关的所有其他信息。

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


CREATE TABLE #BOM
    (
      ItemID NVARCHAR(10) ,
      BOMID NVARCHAR(10) ,
      BOMQTY INT ,
      UnitID NVARCHAR(10) ,
      BOMQTYSERIE INT
    );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100001' , -- ItemID - nvarchar(10)
          N'1A' , -- BOMID - nvarchar(10)
          10 , -- BOMQTY - int
          N'g' , -- UnitID - nvarchar(10)
          5  -- Bomqtyserie - int
        );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100001' , -- ItemID - nvarchar(10)
          N'2A' , -- BOMID - nvarchar(10)
          15 , -- BOMQTY - int
          N'kg' , -- UnitID - nvarchar(10)
          13  -- Bomqtyserie - int
        );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100001' , -- ItemID - nvarchar(10)
          N'3A' , -- BOMID - nvarchar(10)
          16 , -- BOMQTY - int
          N'l' , -- UnitID - nvarchar(10)
          16  -- Bomqtyserie - int
        );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100002' , -- ItemID - nvarchar(10)
          N'1A' , -- BOMID - nvarchar(10)
          18 , -- BOMQTY - int
          N'g' , -- UnitID - nvarchar(10)
          17  -- Bomqtyserie - int
        );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100004' , -- ItemID - nvarchar(10)
          N'2A' , -- BOMID - nvarchar(10)
          20 , -- BOMQTY - int
          N'kg' , -- UnitID - nvarchar(10)
          11  -- Bomqtyserie - int
        );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100002' , -- ItemID - nvarchar(10)
          N'2A' , -- BOMID - nvarchar(10)
          23 , -- BOMQTY - int
          N'kg' , -- UnitID - nvarchar(10)
          19  -- Bomqtyserie - int
        );

INSERT  INTO #BOM
        ( ItemID ,
          BOMID ,
          BOMQTY ,
          UnitID ,
          BOMQTYSERIE
        )
VALUES  ( N'100003' , -- ItemID - nvarchar(10)
          N'2A' , -- BOMID - nvarchar(10)
          25 , -- BOMQTY - int
          N'kg' , -- UnitID - nvarchar(10)
          21  -- Bomqtyserie - int
        );

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


CREATE TABLE #BOMVERSION
    (
      ItemID NVARCHAR(10) ,
      BOMID NVARCHAR(10) ,
      Name NVARCHAR(20) ,
      Active BIT
    );

INSERT  INTO #BOMVERSION
        ( ItemID ,
          BOMID ,
          Name ,
          Active
        )
VALUES  ( N'100002' , -- ItemID - nvarchar(10)
          N'1A' , -- BOMID - nvarchar(10)
          N'100002 Version' , -- Name - nvarchar(10)
          1  -- Active - bit
        );

INSERT  INTO #BOMVERSION
        ( ItemID ,
          BOMID ,
          Name ,
          Active
        )
VALUES  ( N'100002' , -- ItemID - nvarchar(10)
          N'2A' , -- BOMID - nvarchar(10)
          N'100002.1 Version' , -- Name - nvarchar(10)
          1  -- Active - bit
        );

INSERT  INTO #BOMVERSION
        ( ItemID ,
          BOMID ,
          Name ,
          Active
        )
VALUES  ( N'100003' , -- ItemID - nvarchar(10)
          N'3A' , -- BOMID - nvarchar(10)
          N'100003 Version' , -- Name - nvarchar(10)
          1  -- Active - bit
        );

INSERT  INTO #BOMVERSION
        ( ItemID ,
          BOMID ,
          Name ,
          Active
        )
VALUES  ( N'100004' , -- ItemID - nvarchar(10)
          N'4A' , -- BOMID - nvarchar(10)
          N'100004 Version' , -- Name - nvarchar(10)
          1  -- Active - bit
        );

INSERT  INTO #BOMVERSION
        ( ItemID ,
          BOMID ,
          Name ,
          Active
        )
VALUES  ( N'100005' , -- ItemID - nvarchar(10)
          N'5A' , -- BOMID - nvarchar(10)
          N'100005 Version' , -- Name - nvarchar(10)
          1  -- Active - bit
        );

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


CREATE TABLE #INVENTTABLE
    (
      ItemID NVARCHAR(10) ,
      Name NVARCHAR(20) ,
      Product INT
    );

INSERT  INTO #INVENTTABLE
        ( ItemID, Name, Product )
VALUES  ( N'100001', -- ItemID - nvarchar(10)
          N'100001 Name', -- Name - nvarchar(10)
          1  -- Product - int
          );

INSERT  INTO #INVENTTABLE
        ( ItemID, Name, Product )
VALUES  ( N'100002', -- ItemID - nvarchar(10)
          N'100002 Name', -- Name - nvarchar(10)
          2  -- Product - int
          );

INSERT  INTO #INVENTTABLE
        ( ItemID, Name, Product )
VALUES  ( N'100003', -- ItemID - nvarchar(10)
          N'100003 Name', -- Name - nvarchar(10)
          3  -- Product - int
          );

INSERT  INTO #INVENTTABLE
        ( ItemID, Name, Product )
VALUES  ( N'100004', -- ItemID - nvarchar(10)
          N'100004 Name', -- Name - nvarchar(10)
          4  -- Product - int
          );

INSERT  INTO #INVENTTABLE
        ( ItemID, Name, Product )
VALUES  ( N'100005', -- ItemID - nvarchar(10)
          N'100005 Name', -- Name - nvarchar(10)
          5  -- Product - int
          );

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

CREATE TABLE #ECORESPRODUCTTRANSLATION
    (
      Product INT ,
      Name NVARCHAR(20)
    );




INSERT  INTO #ECORESPRODUCTTRANSLATION
        ( Product, Name )
VALUES  ( 1, -- Product - int
          N'100001 Description'  -- Name - nvarchar(10)
          );

INSERT  INTO #ECORESPRODUCTTRANSLATION
        ( Product, Name )
VALUES  ( 2, -- Product - int
          N'100002 Description'  -- Name - nvarchar(10)
          );

INSERT  INTO #ECORESPRODUCTTRANSLATION
        ( Product, Name )
VALUES  ( 3, -- Product - int
          N'100003 Description'  -- Name - nvarchar(10)
          );

INSERT  INTO #ECORESPRODUCTTRANSLATION
        ( Product, Name )
VALUES  ( 4, -- Product - int
          N'100004 Description'  -- Name - nvarchar(10)
          );

INSERT  INTO #ECORESPRODUCTTRANSLATION
        ( Product, Name )
VALUES  ( 5, -- Product - int
          N'100005 Description'  -- Name - nvarchar(10)
          );

WITH    CTE
          AS ( SELECT   B.ItemID AS MainItem ,
                        BV.Name AS BVName ,
                        B.BOMID ,
                        BV.ItemID AS ParentItem ,
                        ECPT.Name AS ParentItemName ,
                        B.BOMQTY ,
                        B.UnitID ,
                        B.BOMQTYSERIE ,
                        1 AS [Level]
               FROM     #BOM AS B
                        JOIN #BOMVERSION AS BV ON BV.BOMID = B.BOMID
                        JOIN #INVENTTABLE AS IT ON IT.ItemID = BV.ItemID
                        JOIN #ECORESPRODUCTTRANSLATION AS ECPT ON ECPT.Product = IT.Product
               WHERE    B.ItemID = '100001'
                        AND BV.Active = 1
               UNION ALL
               SELECT   C.MainItem ,
                        C.BVName ,
                        C.BOMID ,
                        BV.ItemID ,
                        C.ParentItemName ,
                        C.BOMQTY ,
                        C.UnitID ,
                        C.BOMQTYSERIE ,
                        C.[Level] + 1
               FROM     CTE AS C
                        JOIN #BOM AS B ON C.ParentItem = B.ItemID
                        JOIN #BOMVERSION AS BV ON BV.BOMID = B.BOMID
               WHERE    C.[Level] <= 7
             )
    SELECT  MainItem ,
            [1] AS Level1 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE ,
            [2] AS Level2 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE ,
            [3] AS Level3 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE ,
            [4] AS Level4 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE ,
            [5] AS Level5 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE ,
            [6] AS Level6 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE ,
            [7] AS Level7 ,
            BVName ,
            ParentItemName ,
            BOMQTY ,
            UnitID ,
            BOMQTYSERIE
    FROM    CTE PIVOT ( MAX(ParentItem) FOR [Level] IN ( [1], [2], [3], [4],
                                                         [5], [6], [7] ) ) AS pvt;

enter image description here

最佳答案

这是一个易于理解和维护的版本:

    ;
WITH    CTE
          AS ( SELECT   B.RECID AS MainID ,
                        B.ITEMID AS MainItem ,
                        BV.NAME ,
                        BV.ITEMID AS ParentItem ,
                        ECPT.NAME AS ParentItemName ,
                        B.BOMQTY ,
                        B.UNITID ,
                        B.BOMQTYSERIE ,
                        0 AS [level]
               FROM     #BOM B
                        JOIN #BOMVERSION BV ON BV.BOMID = B.BOMID
                        JOIN #INVENTTABLE AS IT ON IT.ITEMID = BV.ITEMID
                        JOIN #ECORESPRODUCTTRANSLATION AS ECPT ON ECPT.PRODUCT = IT.PRODUCT
               WHERE    B.ITEMID = '113621'
                        AND BV.ACTIVE = '1'
               UNION ALL
               SELECT   C.MainID ,
                        C.MainItem ,
                        C.NAME ,
                        BV.ITEMID ,
                        C.ParentItemName ,
                        C.BOMQTY ,
                        C.UNITID ,
                        C.BOMQTYSERIE ,
                        C.[level] + 1
               FROM     CTE C
                        JOIN #BOM B ON C.ParentItem = B.ITEMID
                        JOIN #BOMVERSION BV ON BV.BOMID = B.BOMID
               WHERE    C.[level] <= 6
             )
    SELECT  B.ITEMID ,
            C1.ParentItem AS ParentItem1 ,
            C1.NAME AS BVName1 ,
            C1.ParentItemName AS ParentItemName1 ,
            C1.BOMQTY AS BomQty1 ,
            C1.UNITID AS UnitID1 ,
            C1.BOMQTYSERIE AS BomQtySerie1 ,
            C2.ParentItem AS ParentItem2 ,
            C2.NAME AS BVName2 ,
            C2.ParentItemName AS ParentItemName2 ,
            C2.BOMQTY AS BomQty2 ,
            C2.UNITID AS UnitID2 ,
            C2.BOMQTYSERIE AS BomQtySerie2 ,
            C3.ParentItem AS ParentItem3 ,
            C3.NAME AS BVName3 ,
            C3.ParentItemName AS ParentItemName3 ,
            C3.BOMQTY AS BomQty3 ,
            C3.UNITID AS UnitID3 ,
            C3.BOMQTYSERIE AS BomQtySerie3 ,
            C4.ParentItem AS ParentItem2 ,
            C4.NAME AS BVName2 ,
            C4.ParentItemName AS ParentItemName4 ,
            C4.BOMQTY AS BomQty4 ,
            C4.UNITID AS UnitID4 ,
            C4.BOMQTYSERIE AS BomQtySerie4 ,
            C5.ParentItem AS ParentItem5 ,
            C5.NAME AS BVName5 ,
            C5.ParentItemName AS ParentItemName5 ,
            C5.BOMQTY AS BomQty5 ,
            C5.UNITID AS UnitID5 ,
            C5.BOMQTYSERIE AS BomQtySerie5 ,
            C6.ParentItem AS ParentItem6 ,
            C6.NAME AS BVName6 ,
            C6.ParentItemName AS ParentItemName6 ,
            C6.BOMQTY AS BomQty6 ,
            C6.UNITID AS UnitID6 ,
            C6.BOMQTYSERIE AS BomQtySerie6 ,
            C7.ParentItem AS ParentItem7 ,
            C7.NAME AS BVName7 ,
            C7.ParentItemName AS ParentItemName7 ,
            C7.BOMQTY AS BomQty7 ,
            C7.UNITID AS UnitID7 ,
            C7.BOMQTYSERIE AS BomQtySerie7
    FROM    #BOM B
            LEFT JOIN CTE C1 ON B.RECID = C1.MainID
                                AND C1.[level] = 0
            LEFT JOIN CTE C2 ON B.RECID = C2.MainID
                                AND C2.[level] = 1
            LEFT JOIN CTE C3 ON B.RECID = C3.MainID
                                AND C3.[level] = 2
            LEFT JOIN CTE C4 ON B.RECID = C4.MainID
                                AND C4.[level] = 3
            LEFT JOIN CTE C5 ON B.RECID = C5.MainID
                                AND C5.[level] = 4
            LEFT JOIN CTE C6 ON B.RECID = C6.MainID
                                AND C6.[level] = 5
            LEFT JOIN CTE C7 ON B.RECID = C7.MainID
                                AND C7.[level] = 6
    WHERE   B.ITEMID = '113621'
            AND C1.ParentItem IS NOT NULL;

编辑:

输入:

INSERT  INTO #BOM VALUES  
( 1, N'10', N'1A' ),
( 2, N'20', N'2A' ),
( 3, N'30', N'3A' ),
( 4, N'40', N'4A' ),
( 5, N'50', N'5A' ),
( 6, N'60', N'6A' ),
( 7, N'70', N'7A' ),
( 8, N'80', N'8A' ),

( 9, N'90', N'9A' ),
( 10, N'100', N'10A' ),
( 11, N'110', N'11A' )

INSERT  INTO #BOMVERSION VALUES  
( 1, N'20', N'10 PRE', N'1A' ),
( 2, N'30', N'20 PRE', N'2A' ),
( 3, N'40', N'30 PRE', N'3A' ),
( 4, N'50', N'40 PRE', N'4A' ),
( 5, N'60', N'50 PRE', N'5A' ),
( 6, N'70', N'60 PRE', N'6A' ),
( 7, N'80', N'70 PRE', N'7A' ),

( 8, N'100', N'90 PRE', N'9A' ),
( 9, N'110', N'100 PRE', N'10A' ),
( 9, N'120', N'110 PRE', N'11A' )

INSERT  INTO #Item VALUES  
( 1, N'10', N'10 DESC' ),
( 2, N'20', N'20 DESC' ),
( 3, N'30', N'30 DESC' ),
( 4, N'40', N'40 DESC' ),
( 5, N'50', N'50 DESC' ),
( 6, N'60', N'60 DESC' ),
( 7, N'70', N'70 DESC' ),
( 8, N'80', N'80 DESC' ),

( 9, N'90', N'90 DESC' ),
( 10, N'100', N'100 DESC' ),
( 11, N'110', N'110 DESC' )

输出:

enter image description here

关于SQL 递归 CTE 'where-used'/BOM 爆炸第 2 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30259328/

相关文章:

PHP 多维数组排序

sql-server - 我们可以更新 View 中的真实数据吗?

sql - JSON_MODIFY 删除数组对象

java - 递归比较两个二叉搜索树

java - 如何在不使用循环的情况下递归地从给定字符串中删除 char 数组中的所有字符?

java - 自定义链表: Picking alternate integer elements

sql - J2ME 连接本地主机 nullpointerexception 0

mysql - 按小时分组时,分组依据应返回 0。这个怎么做?

mysql - 从多列中选择最常见的

sql-server - 不带 SQL Server 的 Visual Studio 2015