CTE创建产品层次结构树

时间:2017-02-07 09:22:02

标签: sql-server common-table-expression recursive-cte

我有以下三个表格表示产品数据。简而言之,产品“A”和“B”是最终产品。要找出产品“A”的部件,我们查看“ProductComponents”表,给出ComponentListId = 1。

对“PartsSubcomponents”表查询此ComponentListId告诉我们它有两个子组件,即A11和A12。

A11很小,因为它没有其他子组件。但是,A12存在于“ProductComponents”表中,告诉我们它是用X1和X2制作的。

终产物

EndProductId
A
B
...

ProductComponents

ProductId ComponentListId
A         1
A12       99
...

PartsSubcomponents

ComponentListId SubComponentId
1               A11
1               A12
99              X1
99              X2
...

我需要使用CTE来查找产品及其部件之间的层次结构级别。在这种情况下,结果应该是这样的:

EndProductId,ProductId,ComponentListId,SubcomponentId,Level
A,           A,        1,              A11,           L1
A,           A,        1,              A12,           L1
A,           A12,      99,             X1,            L2
A,           A12,      99,             X2,            L2

1 个答案:

答案 0 :(得分:2)

这是一个简单的递归cte,可以完成你所需要的并产生你想要的输出:

CREATE TABLE #EndProducts
    (
      EndProductId NVARCHAR(1)
    );

INSERT  INTO #EndProducts
        ( EndProductId )
VALUES  ( 'A' ),
        ( 'B' );

CREATE TABLE #ProductComponents
    (
      ProductId NVARCHAR(3) ,
      ComponentListId INT
    );

INSERT  INTO #ProductComponents
        ( ProductId, ComponentListId )
VALUES  ( 'A', 1 ),
        ( 'A12', 99 );

CREATE TABLE #PartsSubcomponents
    (
      ComponentListId INT ,
      SubComponentId NVARCHAR(3)
    ); 

INSERT  INTO #PartsSubcomponents
        ( ComponentListId, SubComponentId )
VALUES  ( 1, 'A11' ),
        ( 1, 'A12' ),
        ( 99, 'X1' ),
        ( 99, 'X2' );

WITH    cte
          AS ( -- anchor member gets level 1
               SELECT   e.EndProductId ,
                        pc.ProductId ,
                        sc.ComponentListId ,
                        sc.SubComponentId ,
                        1 AS [Level]
               FROM     #EndProducts e
               INNER JOIN #ProductComponents pc 
                     ON e.EndProductId = pc.ProductId
               INNER JOIN #PartsSubcomponents sc 
                     ON pc.ComponentListId = sc.ComponentListId
               UNION ALL
               -- recursive member gets the additional data and increments levels
               SELECT   cte.EndProductId ,
                        cte.SubComponentId AS ProductId ,
                        pc.ComponentListId ,
                        sc.SubComponentId ,
                        cte.[Level] + 1 AS [Level]
               FROM     cte
               INNER JOIN #ProductComponents pc 
                     ON cte.SubComponentId = pc.ProductId
               INNER JOIN #PartsSubcomponents sc 
                     ON pc.ComponentListId = sc.ComponentListId
             )
    SELECT  *
    FROM    cte;

DROP TABLE #EndProducts;
DROP TABLE #PartsSubcomponents;
DROP TABLE #ProductComponents;

<强>结果:

EndProductId    ProductId   ComponentListId SubComponentId  Level
A               A           1               A11             1
A               A           1               A12             1
A               A12         99              X1              2
A               A12         99              X2              2