I’m writing a simple program to find what cocktails somebody is able to make given only the ingredients that they already have on hand. The schema looks something like this:
Table CocktailIngredients
cocktailId | ingredientId |
---|---|
0 | 0 |
0 | 2 |
1 | 0 |
1 | 1 |
Table UserIngredients
ingredientId |
---|
0 |
1 |
2 |
I use a relational division to figure out what cocktails the user can make with their current ingredients. However, I don’t like having to add the users ingredients to the DB, especially when they are more than likely logged in as a guest and won’t use the ingredients in the DB again, causing them to be deleted and use write cycles. My question is, is there a way to replace the UserIngredients table by just manually inputting as many ingredients into the query as necessary?
For context, here is my current SQL query:
SELECT cocktailId
FROM CocktailIngredients a
JOIN UserIngredients b ON a.ingredientId = b.ingredientId
GROUP BY cocktailId
HAVING COUNT(*) = (
SELECT COUNT(*) FROM CocktailIngredients c
WHERE c.cocktailId = a.cocktailId
)
2
Answers
Here is one option to do it …
Supply user selected ingredient ids as a comma sparated list – here the list is declared as a cte
Cross Join your table data with user selected list – use Case expressions with Find_In_Set() function to calculate percentage of user ingredients vs total ingredients and get missing ingredient ids.
… now you can propose the coctails to the user either just those with 100% matches or, for instance, 50% oor more along with the list of missing ingredients
You can put UserIngrediets as parameters
See example.
Near classic relational division
Or the remainder of the division
More practical examples.
Test data:
Or
OR simplest case
fiddle