Reputation: 875
I've a new hobby called "turn bad tasting liqueurs into something good" a.k.a. "mix cocktails".
Since I'm a nerd I don't want to look up recipes in a book, read the ingredients list and notice that I've some stuff missing. Instead I want to have a database with all my collected recipes, and ingredients and let the computer tell me which recipes I can 'build' with the ingredients I currently have at home. For this purpose I've this two tables:
Table 1: holds information about a many-to-many relationship
recipe | ingredient
1 | 1
1 | 2
1 | 3
2 | 1
2 | 4
Table 2: information wether this ingredient is available or not
ingredient | available
1 | true
2 | true
3 | true
4 | false
All other tables aren't interesting for my problem.
These two tables can easily INNER JOIN
-ed with ingredient = ingredients.id
to one big table that looks like:
recipe | ingredient | available
1 | 1 | true
1 | 2 | true
1 | 3 | true
2 | 1 | true
2 | 4 | false
If you take a look at this, you'll notice that I can mix the recipe 1, but not recipe two since one ingredient is missing.
What I want to do now is to find a way so that the result looks like:
recipe | all_available
1 | true
2 | false
I already found a way to check if all ingredients for a certain recipe are available or not:
SELECT RtI.recipe, BIT_AND(ingredients.available) AS all_available
FROM RtI
INNER JOIN ingredients ON (ingredients.id = RtI.ingredient)
WHERE RtI.recipe = 1
Which results:
recipe | all_available
1 | true
But you have to search of a specific ID, what I want is not "show me if all ingredients are available for this recipe" but "show me all recipes for which all ingredients are available".
Is there a way to achieve this just by using MySQL queries?
Upvotes: 2
Views: 164
Reputation: 875
Thanks for the great help!
Based on your hints I can now answer my own question and share my final solution with you:
SELECT RtI.recipe, recipes.title, ( SUM(ingredients.available) / COUNT(ingredients.available) ) AS available
FROM RtI
LEFT JOIN ingredients ON (ingredients.id = RtI.ingredient)
LEFT JOIN recipes ON (recipes.id = RtI.recipe)
GROUP BY RtI.recipe
ORDER BY ( SUM(ingredients.available) / COUNT(ingredients.available) ) DESC, recipes.title
This gives me a table like:
recipe | title | available
1 | Pina Colada | 1.00
2 | Caipirinha | 0.50
It's a bit more to write with all the brackets and functions, but I think this is what "views" are for.
Upvotes: 0
Reputation: 1
Use ORDER BY: SELECT r.recipe AS recipe, BIT_AND( i.available ) AS all_available FROM RtI AS r INNER JOIN ingredients AS i ON ( r.ingredient = i.ingredient ) GROUP BY r.recipe
Upvotes: 0
Reputation: 28196
Try
SELECT recipe, MIN(COALESCE(ingredients.available,0)) all_available
FROM rti LEFT JOIN ingredients ON ingredients.id=rti.ingredient
GROUP BY recipe
all_available
will be 0
for recipes with missing ingredients and 1
for 'complete' recipes.
Edit
Just in case, the ingredient is not even listed in the ingredients table I added a COALESCE
. Probably not necessary, since the RtI
table is probably machine generated and will only conatin valid id
s ...
Upvotes: 1
Reputation: 191749
Remove the WHERE
condition and instead use GROUP BY RtI.recipe
Upvotes: 1