SQL递归CTE' where-used' / BOM爆炸

时间:2015-05-14 09:25:41

标签: sql-server dynamics-ax-2012-r2

我尝试做的只是对BOM表(物料清单)中的项目从BOMVERSION获取相关组件/产品,然后为那些相关组件/产品获取相关组件和产品等低至7个级别。然后,我想转动结果,以便将相关项放在mydata['categorized_value'] = mydata.apply(lambda x: x['original_wt'] if x['categorized'] == 'original' else x['predicted_wt'], axis=1)

请参阅附带的示例数据和代码。我使用的是动态AX 2012 R2,但此示例可应用于使用材料/产品的任何系统。然而,我无法完成我的查询(我知道我没有数据表格和分区我为了简单而遗漏了)。 BOM表中的关系是itemid,通过BOMID与BOMVERSION中的itemid相关。

更新:我已经简化了数据等以使其尽可能简单/清晰,因此木材,金属,玻璃材料本身可以用于制造各种产品和材料,并且可以组合以制造产品或材料。因此,我想从一个基本组件开始,然后按级别分解关系。

DDL + DML:

0, 1, 2, 3, 4, 5, 6, 7

输出看起来像enter image description here

1 个答案:

答案 0 :(得分: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