从层次表SQL中按关系顺序选择所有祖先

从层次表SQL中按关系顺序选择所有祖先,sql,sql-server,Sql,Sql Server,我有一个这样的表,在SQLServer的同一个表中有一个父子关系 Finished Product| Quantity Unit Bill Of Material ---------------------------------------------------------------------------------------- Product 1 1 Nos

我有一个这样的表,在SQLServer的同一个表中有一个父子关系

Finished Product|   Quantity           Unit                Bill Of Material
----------------------------------------------------------------------------------------
Product 1             1                 Nos                    Product 2
Product 1             1                 Nos                    Product 3
Product 1             1                 Nos                    Product 4
Product 2             2                 Nos                    Product 5
Product 2             1                 Nos                    Product 6
Product 2             3                 Nos                    Product 7
Product 2             1                 Nos                    Product 8
Product 3             3                 Nos                    Product 9
Product 3             2                 Nos                    Product 10
Product 3             1                 Nos                    Product 5
Product 3             1                 Nos                    Product 6
Product 4             2                 Nos                    Product 5
Product 4             2                 Nos                    Product 7
Product 4             2                 Nos                    Product 8
Product 5             2                 Nos                    Product 6
Product 5             3                 Nos                    Product 7
Product 5             4                 Nos                    Product 11
Product 5             2                 Nos                    Product 12
因此,当我检查材料产品6与最终产品产品1的关系时,我必须按以下顺序获得表格

Quantity Unit Reference Item -------------------------------------------- 6 Nos Product 5 1 Nos Product 3 1 Nos Product 2 因为产品6不直接连接到产品1,而是通过产品1子级间接连接

为什么结果表包含产品5的6个编号,是因为产品6通过产品5以3种不同的方式连接到产品1。每个产品5我们需要2个产品6 i、 e


以上序列仅考虑乘积5的关系。

可以使用递归CTE。对于与成品1相关的所有可能行,将@Material设置为NULL。同样,要查看物料产品6的所有行,请将@FinishedProduct设置为NULL

-- Create CTE  
DECLARE @Material VARCHAR(50) = 'Product 6',  
@FinishedProduct VARCHAR(50) = 'Product 1'  

;WITH   recursiveProduct  
AS   
(  
   -- Generate component level line, effectively where "parent" is null  
    SELECT  p1.Material,  
            CAST(( p1.FinishedProduct + ' --- ' + p1.Material ) AS VARCHAR(MAX)) FinishedProductList,  
            p1.FinishedProduct  
    FROM    dbo.Products p0  
    RIGHT JOIN dbo.Products p1 ON p0.FinishedProduct = p1.Material  
    WHERE   p0.Material IS NULL AND COALESCE(@Material,p1.Material) = p1.Material  

   UNION ALL

    -- Now the recursive bit
   SELECT   p2.Material,  
            CAST(( p2.FinishedProduct + ' --- ' + rp.FinishedProductList ) AS VARCHAR(MAX)) FinishedProductList,
            p2.FinishedProduct  
   FROM     recursiveProduct rp JOIN dbo.Products p2 ON rp.FinishedProduct = p2.Material  
 )  
-- Select data of interest  
SELECT FinishedProductList FROM recursiveProduct WHERE COALESCE(@FinishedProduct, FinishedProduct) = FinishedProduct  
如果其他人想编写代码以获得更好的答案,下面是生成测试数据的代码。我假设这个单位在这个问题上是无关的

IF OBJECT_ID('Products', 'U') IS NOT NULL  
    DROP TABLE Products  
GO  
CREATE TABLE Products 
( FinishedProduct VARCHAR(50) , Quantity INT , Material VARCHAR(50) )
GO
INSERT  dbo.Products
VALUES  ( 'Product 1', 1, 'Product 2' ),
        ( 'Product 1', 1, 'Product 3' ),
        ( 'Product 1', 1, 'Product 4' ),
        ( 'Product 2', 2, 'Product 5' ),
        ( 'Product 2', 1, 'Product 6' ),
        ( 'Product 2', 3, 'Product 7' ),
        ( 'Product 2', 1, 'Product 8' ),
        ( 'Product 3', 3, 'Product 9' ),
        ( 'Product 3', 2, 'Product 10' ),
        ( 'Product 3', 1, 'Product 5' ),
        ( 'Product 3', 1, 'Product 6' ),
        ( 'Product 4', 2, 'Product 5' ),
        ( 'Product 4', 2, 'Product 7' ),
        ( 'Product 4', 2, 'Product 8' ),
        ( 'Product 5', 2, 'Product 6' ),
        ( 'Product 5', 3, 'Product 7' ),
        ( 'Product 5', 4, 'Product 11' ),
        ( 'Product 5', 2, 'Product 12' )
GO  

您使用的是哪种数据库管理系统?博士后?Oracle?对不起,你的问题是什么?它实际上是一个BOM表。这意味着组装产品BOM。最终产品1由三种产品衍生而来,每种产品都是由层次结构中的其他产品衍生而来。我需要找出一种特殊的原材料与他的父母有什么关系;意思是直接的还是祖传的?对不起,问题仍然不清楚:在你的评论中,你说的是直接的还是祖传的。然而,在你问题的期望结果表中,你只有产品5、3和2,它们是父母6的直系父母,而不是所有的祖先。我现在对问题做了一些修改,你明白了吗?我需要的答案是我在问题中提到的第二个表。您可以修改查询以获得这样的结果吗?抱歉,您发布时错过了您的查询。作为回答,一种方法是简单地修改注释为感兴趣的Select数据的最后一个查询,例如从recursiveProduct中选择FinishedProductList+'.'COALESCE@FinishedProduct,FinishedProduct=FinishedProduct和FinishedProductList,如“%Product 5%”
IF OBJECT_ID('Products', 'U') IS NOT NULL  
    DROP TABLE Products  
GO  
CREATE TABLE Products 
( FinishedProduct VARCHAR(50) , Quantity INT , Material VARCHAR(50) )
GO
INSERT  dbo.Products
VALUES  ( 'Product 1', 1, 'Product 2' ),
        ( 'Product 1', 1, 'Product 3' ),
        ( 'Product 1', 1, 'Product 4' ),
        ( 'Product 2', 2, 'Product 5' ),
        ( 'Product 2', 1, 'Product 6' ),
        ( 'Product 2', 3, 'Product 7' ),
        ( 'Product 2', 1, 'Product 8' ),
        ( 'Product 3', 3, 'Product 9' ),
        ( 'Product 3', 2, 'Product 10' ),
        ( 'Product 3', 1, 'Product 5' ),
        ( 'Product 3', 1, 'Product 6' ),
        ( 'Product 4', 2, 'Product 5' ),
        ( 'Product 4', 2, 'Product 7' ),
        ( 'Product 4', 2, 'Product 8' ),
        ( 'Product 5', 2, 'Product 6' ),
        ( 'Product 5', 3, 'Product 7' ),
        ( 'Product 5', 4, 'Product 11' ),
        ( 'Product 5', 2, 'Product 12' )
GO