Найти предметы, где все запчасти есть в наличии - PullRequest
0 голосов
/ 27 марта 2012

Надеюсь, довольно простой запрос, но мой разум просто не работает сегодня днем.У меня есть следующие таблицы:

tblCocktail
CockTailID  CocktailName
1           Alexander

tblCocktailIngredient
CocktailID  IngredientID   Amount   UnitID
1           1              3        1
1           2              3        1
1           3              3        1

tblIngredient
IngredientID  IngredientName   OnHandAmount   OnHandUnitID
1             Cognac           .75            2
2             Creme de Cacao   .9             2
3             Cream            .5             2

tblUnitConversion
FromUnitID    ToUnitID   Factor 
1             2          100

Я пытаюсь найти список коктейлей, которые я могу приготовить, так как у меня достаточно всех ингредиентов.У меня есть следующий запрос:

SELECT tblCocktail.CocktailName
FROM tblCocktail INNER JOIN (tblIngredient INNER JOIN (tblCocktailIngredient INNER JOIN  tblUnitConversion ON tblCocktailIngredient.UnitID = tblUnitConversion.ToUnitID) ON (tblIngredient.IngredientID = tblCocktailIngredient.IngredientID) AND (tblIngredient.OnHandUnit = tblUnitConversion.FromUnitID)) ON tblCocktail.CocktailID = tblCocktailIngredient.CocktailID
WHERE ((([tblCocktailIngredient].[Amount]*[Factor])<[tblIngredient].[OnHandAmount]));

Это даст список всех Коктейлей и связанных с ними ингредиентов, где onHand больше, чем Сумма, однако я только хочу перечислить Коктейли, где ВСЕ ингредиентов достаточноколичество в наличии.

Ответы [ 3 ]

1 голос
/ 27 марта 2012

Не простой запрос, потому что Access требует, чтобы вы были очень откровенны в отношении сложных внешних объединений.

SELECT tblCocktail.CocktailID, tblCocktail.CocktailName, sum(IIf(isnull(onhand.IngredientID),1,0)) AS missingIngredients
FROM (tblCocktail INNER JOIN tblCocktailIngredient ON tblCocktail.CocktailID=tblCocktailIngredient.CocktailID)
LEFT JOIN (
    SELECT tblIngredient.IngredientID, tblIngredient.OnHandAmount*tblUnitConversion.Factor AS OnHandAmount, tblUnitConversion.FromUnitID AS OnHandUnitID
    FROM tblIngredient INNER JOIN tblUnitConversion ON tblUnitConversion.ToUnitID=tblIngredient.OnHandUnitID
)  AS onhand
ON (tblCocktailIngredient.IngredientID=onhand.IngredientID) AND (tblCocktailIngredient.UnitID=onhand.OnHandUnitID) AND (tblCocktailIngredient.Amount<=onhand.OnHandAmount)
GROUP BY tblCocktail.CocktailID, tblCocktail.CocktailName
HAVING sum(IIf(isnull(onhand.IngredientID),1,0))=0

(редактировать: понял, что мне нужен только один подзапрос)

Чтобы уточнить, яиспользовал внешнее соединение, чтобы определить, достаточно ли ингредиентов под рукой в ​​коктейле.Исходя из этого, группировка по коктейлю позволяет мне подсчитать количество отсутствующих / не пропущенных ингредиентов в предложении HAVING.

Обратите внимание, что подзапрос 'onhand' может быть полезен для создания в качестве именованного запроса, чтобы упростить егопосмотрите, что у вас под рукой в ​​данном отряде.

1 голос
/ 27 марта 2012
SELECT tblCocktail.CocktailName
FROM tblCocktail
WHERE   (   SELECT  COUNT(*) 
            FROM    tblCocktailIngredient 
            WHERE tblCocktailIngredient.CocktailID = tblCocktail.CockTailID) 
        =
        (   SELECT  COUNT(*)
            FROM    tblIngredient 
                    INNER JOIN (tblCocktailIngredient
                                INNER JOIN tblUnitConversion 
                                    ON tblCocktailIngredient.UnitID = tblUnitConversion.FromUnitID)
                        ON (tblIngredient.IngredientID = tblCocktailIngredient.IngredientID)
                            AND (tblIngredient.OnHandUnitId = tblUnitConversion.ToUnitID) 


            WHERE   [tblCocktailIngredient].[Amount] <= [tblIngredient].[OnHandAmount]*[Factor]
                    AND tblCocktailIngredient.CocktailID = tblCocktail.CocktailID )
0 голосов
/ 27 марта 2012

Я считаю, что это то, что вы ищете:

select result1.CocktailName
from (
    select tblCocktail.CocktailName, count(*) as NumIngredientsPerCocktail
    from tblCocktail
    inner join tblCocktailIngredient
       on tblCocktail.CocktailID = tblCocktailIngredient.CocktailID
    group by tblCocktail.CocktailName
) as result1
inner join (
    select tblCocktail.CocktailName, count(*) as NumberAvailableIngredientsForCocktail
    from tblCocktail 
    inner join tblCocktailIngredient
       on tblCocktail.CocktailID = tblCocktailIngredient.CocktailID
    inner join tblIngredient
       on tblCocktailIngredient.IngredientID = tblIngredient.IngredientID
    inner join tblUnitConversion
       on tblUnitConversion.FromUnitID = tblCocktailIngredient.UnitID
      and tblUnitConversion.ToUnitID = tblIngredient.OnHandUnitID
    where tblIngredient.OnHandAmount * tblUnitConversion.Factor >= tblCocktailIngredient.Amount
    group by tblCocktail.CocktailName
) as result2
on result1.NumIngredientsPerCocktail = result2.NumberAvailableIngredientsForCocktail
and result1.CocktailName = result2.CocktailName
...