Hello. I want to select dishes which has the only the exactly selected ingredient alias? For example: Ingredient alias table:
x
+----+----------+
| id | Name |
+----+----------+
| 22 | potato |
| 23 | rice |
| 29 | chicken |
+----+----------+
Ingredient table:
+------+-----------+----------+-------+------+----------+
| id | name | proteins | carbs | fats | alias_id |
+------+-----------+----------+-------+------+----------+
| 3043 | Chicken 1 | 44.0 | 3.0 | 3.0 | 29 |
| 3025 | Rice 1 | 44.0 | 32.0 | 23 | 23 |
| 3024 | Rice 2 | 23.0 | 22.0 | 33.0 | 23 |
| 3042 | Chicken 2 | 22.0 | 22.0 | 3.0 | 29 |
| 3022 | Potato 1 | 22.0 | 22.0 | 32.0 | 22 |
| 3021 | Potato 2 | 20.0 | 30.0 | 40.0 | 22 |
| 3041 | Chicken 3 | 11.0 | 11.0 | 11.0 | 29 |
| 3026 | Rice 3 | 1.0 | 1.0 | 1.0 | 23 |
| 3023 | Potato 3 | 1.0 | 2.0 | 3.0 | 22 |
+------+-----------+----------+-------+------+----------+
Table Meal:
+----+-----------------------------------------+
| id | name |
+----+-----------------------------------------+
| 1 | Meal with Chicken 1 and Rice 1 |
| 2 | Meal with Chicken 1 and Rice 2 |
| 3 | Meal with Chicken 2 Potato 1 |
| 4 | Meal with Chicken 2 Potato 1 and Rice 1 |
+----+-----------------------------------------+
Table meal_ingredient:
+-------+---------+---------------+--------+------+
| id | meal_id | ingredient_id | weight | role |
+-------+---------+---------------+--------+------+
| 13366 | 1 | 3043 | 13 | 1 |
| 13367 | 1 | 3025 | 1 | 1 |
| 13368 | 2 | 3043 | 12 | 2 |
| 13369 | 2 | 3024 | 8 | 3 |
| 13370 | 3 | 3042 | 22 | 1 |
| 13371 | 3 | 3022 | 1 | 1 |
| 13372 | 4 | 3042 | 3 | 1 |
| 13373 | 4 | 3022 | 3 | 3 |
| 13374 | 4 | 3024 | 2 | 2 |
+-------+---------+---------------+--------+------+
How I can get meals only which has ingredients only with ingredient aliases Potato and chicken? In my example, the result must be a meal with id 3 Meal with Chicken 2 Potato 1 ?
Advertisement
Answer
You need to join all 4 tables, group by meal and put the condition in the HAVING clause:
select m.id, m.name
from ingredient_alias ia
inner join ingredient i on i.alias_id = ia.id
inner join meal_ingredient mi on mi.ingredient_id = i.id
inner join meal m on m.id = mi.meal_id
group by m.id, m.name
having
count(distinct ia.name) = 2
and
sum(ia.name not in ('potato', 'chicken')) = 0
See the demo.
Results:
| id | name |
| --- | -------------------------------- |
| 3 | Meal with Chicken 2 and Potato 1 |