1

我看过一些类似问题的帖子,但解决方案对我不起作用,因为我不想让中层父母像孩子一样。我相当肯定这Recursive Common Table Expressions会成功。

基本上,我有一个表格列出了所有的父子关系,但它只有 1 级深。我想查询此表,以便对于所有父项,返回所有底层后代,以获得任意深度级别。例如:

 What the table looks like               what I'd like my query to return

     child | parent                             child | parent
     --------------                             --------------
       a1  |  b1                                  a2  |  b1
       a2  |  b1                                  a3  |  b1
       a3  |  b1                                  c1  |  b1
       c1  |  a1                                  c2  |  b1
       c2  |  a1                                  c1  |  a1
                                                  c2  |  a1

我一直在尝试的查询比我看到的示例要复杂一些,因为我必须连接多个表才能使事情顺利进行。我必须将数据库 ID 与名称等连接起来。我还没有看到有人像这样只要求底层后代。

我正在处理一个食谱数据库,所以这些“父母”是食谱,而“孩子”是库存项目。但是库存项目可能是子配方;由其他库存项目甚至可能其他子配方组成。这就是这种任意深度的来源。我试图编写的查询是一个“购物清单”——所以对于每个存在的食谱(食谱或子食谱),我想列出所有它的底层库存项目(即没有子配方,只有它们的单个组件)。幸运的是,我的一张桌子有一列,其中有一点表明一种成分作为子配方的状态。

到目前为止,这是我正在使用的,但没有给出预期的结果:

RecpInv('rInv') 将父母与孩子相关联(项目 ID 与配方 ID)

Inv ('inv') 将项目 ID 与项目名称相关联

Recipe ('recipes')将配方 ID 与配方名称相关联

WITH ingredients AS(
    SELECT 
        inv.ItemName AS 'Inventory Item',
        recipes.RecipeName AS 'Recipe',
        rInv.RecipeID AS 'Recipe ID',
        rInv.ItemID AS 'Item ID'

    FROM [DataDir].[dbo].[RecpInv] AS rInv
    INNER JOIN [DataDir].[dbo].[Inv] AS inv
        ON inv.ItemID = rInv.ItemID
    INNER JOIN [DataDir].[dbo].[Recipe] AS recipes
        ON recipes.RecipeID = rInv.RecipeID

    WHERE recipes.ProfCentID = @profitCenter
        AND inv.ProfCentID = @profitCenter

    UNION ALL

    SELECT 
        inv2.ItemName AS 'Inventory Item',
        recipes2.RecipeName AS 'Recipe',
        rInv2.RecipeID AS 'Recipe ID',
        rInv2.ItemID AS 'Item ID'

    FROM  [DataDir].[dbo].[RecpInv] AS rInv2
    INNER JOIN [DataDir].[dbo].[Recipe] AS recipes2
        ON rInv2.RecipeID = recipes2.RecipeID
    INNER JOIN [DataDir].[dbo].[Inv] AS inv2
        ON rInv2.ItemID = inv2.ItemID
    INNER JOIN ingredients
        ON rInv2.ItemID = ingredients.[Recipe ID]

    WHERE recipes2.ProfCentID = @profitCenter
        AND inv2.ProfCentID = @profitCenter
        AND inv2.SubRecipe = 0
)

SELECT
    ingredients.[Inventory Item],
    ingredients.[Recipe]

    FROM ingredients

    ORDER BY ingredients.[Recipe]

以下是部分查询结果。我从这个查询中得到 32,000 行:

mayonnaise, vegan         Aioli, Roasted Garlic
Roasted Garlic Puree      Aioli, Roasted Garlic
salt, kosher              Aioli, Roasted Garlic
juice, lemon              Aioli, Roasted Garlic
mayonnaise, canola        Aioli, Truffle
spice, black truffle rub  Aioli, Truffle
pepper, black ground      Aioli, Truffle
mustard, stoneground      Aioli, Truffle
Garlic, Minced            Aioli, Truffle

这些是右侧食谱的正确顶级成分。左栏中以大写字母开头的项目是子配方,由库存项目和/或子配方组成。我不想要左边的任何子食谱。只是他们的底层组件。因此,“蒜泥蛋黄酱,烤大蒜”不应该将“烤大蒜泥”作为其成分之一。应该包括“烤大蒜泥”的底层组件。'大蒜,剁碎'也是如此。

我意识到这是一个很大的问题,但任何帮助表示赞赏。

4

1 回答 1

0

不确定这是否是最有效或最有说服力的方法,但它给出了我正在寻找的结果:

WITH ingredients AS
(
    SELECT 
        inv.ItemName AS 'Inventory Item',
        recipes.RecipeName AS 'Recipe',
        rInv.RecipeID AS 'Recipe ID',
        rInv.ItemID AS 'Item ID',
        inv.SubRecipe AS 'Sub'

    FROM [DataDir].[dbo].[RecpInv] AS rInv
    INNER JOIN [DataDir].[dbo].[Inv] AS inv
        ON inv.ItemID = rInv.ItemID
    INNER JOIN [DataDir].[dbo].[Recipe] AS recipes
        ON recipes.RecipeID = rInv.RecipeID

    WHERE recipes.ProfCentID = @profitCenter
        AND inv.ProfCentID = @profitCenter

    UNION ALL

    SELECT 
        inv2.ItemName AS 'Inventory Item',
        ingredients.[Recipe] AS 'Recipe',
        ingredients.[Recipe ID] AS 'Recipe ID',
        inv2.ItemID AS 'Item ID',
        inv2.SubRecipe AS 'Sub'

    FROM  [DataDir].[dbo].[RecpInv] AS rInv2
    INNER JOIN [DataDir].[dbo].[Recipe] AS recipes2
        ON rInv2.RecipeID = recipes2.RecipeID
    INNER JOIN [DataDir].[dbo].[Inv] AS inv2
        ON rInv2.ItemID = inv2.ItemID
    INNER JOIN ingredients
        ON rInv2.RecipeID = ingredients.[Item ID]

    WHERE recipes2.ProfCentID = @profitCenter
        AND inv2.ProfCentID = @profitCenter
)

SELECT DISTINCT
    ingredients.[Inventory Item],
    ingredients.[Recipe]

    FROM ingredients

    WHERE ingredients.[Sub] = 0

    ORDER BY ingredients.[Recipe], ingredients.[Inventory Item]
于 2020-04-15T18:07:58.480 回答