a different way:
Version 2 (as stored procedure) revised
select r.name
from recipes r
where r.id = (select t1.recipe_id
from RecipeIngredients t1 inner join
RecipeIngredients t2 on t1.recipe_id = t2.recipe_id
and t1.ingredient_id = @recipeId1
and t2.ingredient_id = @recipeId2)
Edit 2:
[before people start screaming] :)
This can be placed at the top of version 2, which will allow to query by name instead of passing in the id.
select @recipeId1 = recipe_id from Ingredients where name = @Ingredient1
select @recipeId2 = recipe_id from Ingredients where name = @Ingredient2
I've tested version 2, and it works. Most users where linking on the Ingredient table, in this case was totally not needed!
Edit 3: (test results);
When this stored procedure is run these are the results.
The results are of the format (First Recipe_id ; Second Recipe_id, Result)
1,1, Failed
1,2, 'banana cream pie'
1,3, 'chocolate banana surprise'
2,1, 'banana cream pie'
2,2, Failed
2,3, 'chocolate cream pie'
3,1, 'chocolate banana surprise'
3,2, 'chocolate cream pie'
3,3, Failed
Clearly this query does not handle case when both constraints are the same, but works for all other cases.
Edit 4:(handling same constraint case):
replacing this line:
r.id = (select t1...
to
r.id in (select t1...
works with the failed cases to give:
1,1, 'banana cream pie' and 'chocolate banana surprise'
2,2, 'chocolate cream pie' and 'banana cream pie'
3,3, 'chocolate cream pie' and 'chocolate banana surprise'