如何为子集构建基于集合的查询?

时间:2014-07-24 15:14:57

标签: sql algorithm

我有一个以下结构的数据库(图片显示简化版)

enter image description here

我应该如何构建查询以仅获取可以烹饪的那些食谱,即对于每个成分中的每种成分都要求清晰度> availableQuantity?

我试过了:

SELECT r.Name
FROM
   Receipe r
   JOIN RecipeIngredients ri ON ri.RecipeID = r.Id
   JOIN Ingredients i ON i.ID = ri.IngredientsId
WHERE
   ri.RequiredQuantity - i.AvailableQuantity > 0

但我不确定这是否正确,因为我认为这只会返回可用的成分。我应该如何修改上述查询以仅生成每种成分可用的配方? 谢谢你的帮助

----编辑----

也许是这样的:

SELECT r.Name
FROM
(
    SELECT   r.Name AS Name
             r.Id AS Id
           , CASE (
                WHEN (ri.RequiredQuantity - i.AvailableQuantity >= 0)
                THEN 1
             ) AS Available
    FROM
       Receipe r
       JOIN RecipeIngredients ri ON ri.RecipeID = r.Id
       JOIN Ingredients i ON i.ID = ri.IngredientsId
    WHERE
           ri.RequiredQuantity - i.AvailableQuantity >= 0  
    GROUP BY
       r.Id
) AS results
WHERE
    // count of ingredients with value 1 for each recipe == count of all required ingredients for this recipe

但是我不知道如何写上面代码的最后一行

2 个答案:

答案 0 :(得分:2)

您现在正在做的是加入配方项目(复制配方数据),然后将复制品分开。这是一种反模式。它不会捕获您的意图并使查询更难实现。

重新制定查询。你想要的是所有食谱,其中数量条件包含所有项目。也就是说“不存在条件不存在的项目”。

select *
from recipes r
where not exist (
 select *
 from RecipeIngredients ri
 JOIN Ingredients i ON i.ID = ri.IngredientsId
 where
  r.id = ri.recipeid --join condition
  and not (ri.RequiredQuantity - i.AvailableQuantity >= 0) --quantity condition
)

答案 1 :(得分:1)

以下查询首先获取所需成分和可用成分的数量。如果所需成分的数量=可用成分的数量,则选择配方。

SELECT 
    R.*
FROM Recipe R
INNER JOIN
(
SELECT 
    RI.RecipeID,
    Count(RI.IngredientsID) Required_Ingredients,
    SUM
    (CASE
        WHEN I.AvailableQuantity > RI.RequiredQuantity THEN 1
        ELSE 0
    END) Available_Ingredients  
FROM RecipeIngredients RI
INNER JOIN Ingredients I ON RI.IngredientsID = I.ID
GROUP BY RI.RecipeID
) Availability
ON R.ID = Availability.RecipeID
WHERE Availability.Required_Ingredients = Availability.Available_Ingredients