Выборка записей из many-to-many таблицы (PostgreSQL)

Коллеги, дайте ума, пожалуйста. Проще всего будет объяснить на примере "повареной книги". Есть рецепты и есть ингредиенты. Many-to-many табличка выглядит примерно так:

-------------------------
|  recipes_ingredients  |
-------------------------
recipe_id | ingredient_id
-------------------------
r_id_1    | i_id_1
r_id_1    | i_id_2
r_id_2    | i_id_3
r_id_2    | i_id_2
r_id_2    | i_id_4
r_id_3    | i_id_1
r_id_3    | i_id_2

Пользователь хочет выбрать все рецепты, которые содержат только ингредиенты i_id_1 И i_id_2. Эти продукты могут содержаться и в других рецептах, но поскольку в этих других рецептах содержатся и другие продукты, которых у пользователя нет, то в результат должны попасть 2 рецепта с r_id_1 и r_id_3. Я пробовал выборки с any и all, вроде такой:

select * from recipes_ingredients
where ingredient_id = any('{i_id_1, i_id_2}');

но очевидно, что в таком варианте выбирается И рецепт с r_id_2.

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


Ответы (1 шт):

Автор решения: Akina

Обычное логическое деление. В общем случае можно как-то так:

SELECT recipe_id 
FROM recipes_ingredients
GROUP BY recipe_id 
HAVING SUM((ingredient_id IN ( i_id_1, i_id_2 )) :: INT ) = 2
   AND SUM((ingredient_id NOT IN ( i_id_1, i_id_2 )) :: INT ) = 0
→ Ссылка