2015-05-15 5 views
-1

Для начала, некоторая справочная информация. Я создаю простую базу данных рецептов, и я пытаюсь создать запрос, который покажет мне, что я могу сделать, основываясь на элементах в моей кладовой. Схемы таблиц являются следующими:SQL multi-table составной ключ уникальный запрос

RECIPE(*RecipeID*, RecipeName) 
RECIPE_INGREDIENT(***RecipeID***, **IngredientID**) 
INGREDIENT(*IngredientID*, IngredientName) 
PANTRY_ITEM(*ItemID*, ItemName) 

Поля в таблице RECIPE_INGREDIENT составляет составной ключ и оба внешних ключей в рецепт (RecipeID) и таблицу ингредиента (IngredientID). Я использую следующие тестовые данные:

RECIPE table 
RecipeID,RecipeName 
1,'food 1' 
2,'food 2' 

INGREDIENT Table 
IngredientID, IngredientName 
1,'ing 1' 
2,'ing 2' 
3,'ing 3' 

RECIPE_INGREDIENT table 
RecipeID,IngredientID 
1,1 
1,2 
2,2 
2,3 

PANTRY_ITEM table 
ItemID,ItemName 
1,'ing 2' 
2,'ing 3' 

Поэтому в основном я пытаюсь запросить список RecipeNames на основе элементов есть в моей кладовой. Под этим я подразумеваю, что у меня должны быть все ингредиенты для рецепта в моей кладовой, чтобы он был добавлен в список. Поэтому идеальный запрос, основанный на данных теста, приведет только к «пищевому 2». Проблема, с которой я сталкиваюсь, - это «все ингредиенты» для части рецепта.

Я пробовал несколько разных запросов, и все они приводят к возврату каждого рецепта.

SELECT RecipeName FROM RECIPE WHERE RecipeID IN (SELECT RecipeID FROM RECIPE_INGREDIENT WHERE IngredientID IN (SELECT IngredientID FROM INGREDIENT WHERE IngredientName IN (SELECT ItemName FROM PANTRY_ITEM))) 

Есть ли у кого-нибудь идеи относительно того, как я могу это сделать? Есть ли возможный запрос для этого, или мне придется реструктурировать мою базу данных?

ответ

1

Во-первых, если вы можете поставить только ингредиенты в кладовую ваша pantry схема должна скорее выглядеть следующим образом

CREATE TABLE pantry 
(
    IngredientID int, 
    FOREIGN KEY (IngredientID) REFERENCES ingredient (IngredientID) 
); 

Теперь вы можете использовать HAVING положение, чтобы получить желаемый результат

SELECT recipename 
    FROM 
(
    SELECT recipeid 
    FROM recipe_ingredient ri LEFT JOIN pantry p 
     ON ri.ingredientid = p.ingredientid 
    GROUP BY recipeid 
    HAVING COUNT(*) = COUNT(p.ingredientid) 
) q JOIN recipe r 
    ON q.recipeid = r.recipeid 

Выход:

 
| RecipeName | 
|------------| 
|  food 2 | 

Вот SQLFiddle демо

0

Это НЕ РАБОТАЕТ, но это возможно без изменения схемы. Я бы порекомендовал хотя, возможно, вам стоит подумать о том, что ваш идентификатор таблицы PANTRY соответствует идентификатору ингредиента ...

По существу, мы должны найти в любое время значение NULL при сравнении ингредиента рецепта с его эквивалентом в кладовой. Любой экземпляр NULL в подзапросе означает отсутствие элемента ... Поэтому мы просто генерируем список исключений и сравниваем результаты с этим.

SELECT RecipeID AS _id, RecipeName FROM RECIPE WHERE RecipeID NOT IN (
    SELECT d.RecipeId FROM (
    SELECT p.ItemID, r.RecipeID FROM PANTRY_ITEM p 
     JOIN INGREDIENT i ON (p.ItemName = i.IngredientName) 
     RIGHT JOIN RECIPE_INGREDIENT ri ON (ri.IngredientId = i.IngredientId) 
     RIGHT JOIN RECIPE r ON (r.RecipeId = ri.RecipeId) 
) d WHERE d.ItemID IS NULL 
); 
+0

Это был бы более простой запрос, если бы идентификатор кладовой соответствовал идентификатору ингредиента ... но, как сейчас, так оно и будет. –

0

Вот ваш ответ

select r1.recipeName from recipe r1 where r1.recipeName not in 
(
select r.recipeName from recipe r 
inner join 
recipe_ingredient ri 
on r.recipeid=ri.RecipeID 
inner JOIN 
ingredient i 
on ri.IngredientID=i.ingredientid and 
i.IngredientName not in (select itemname from pantry_item)) 
0

На самом деле, я не понимаю, почему вам нужно больше, чем двух таблиц. В таблице «Рецепты» требуется еще два поля. Единица измерения (tsp, cup, oz и т. Д.) И сколько из этого измерения требуется для рецепта. В таблице Ингредиентов нужны те же два поля, только это количество, доступное в кладовой. Вам нужна другая единица измерения, потому что рецепт может вызвать чашку сахара, но вы покупаете сахар по фунту.

Вам также понадобится udf для конвертирования с одного устройства на другой, поэтому, если рецепт требует наличия 2 ч.л. ванили и кладовая показывает 1 унцию влево, этого достаточно?

Затем просто выполните внешнее соединение между рецептами и ингредиентами и игнорируйте те, у кого есть нулевые ингредиенты (нет или недостаточно ингредиентов в кладовой).

Смежные вопросы