Question

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?

Était-ce utile?

La solution 4

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.

Autres conseils

Remove the WHERE condition and instead use GROUP BY RtI.recipe

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 ids ...

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top