Home > Net >  Recursive join to the same table using where clause from additional table
Recursive join to the same table using where clause from additional table

Time:03-17

Question is related to Unlimited join to the same table until exists but brings an additional table to the query. Tables:

ingredients - contains ingredient IDs and names

ingredient_id|ingredient_name
1            |Water
2            |Salt
3            |Fancy Sauce
4            |Spices
5            |Pepper
6            |Chili

ingredients_to_ingredients - contains optional sub-ingredients for each ingredient

ingredient_id|mapped_ingredient_id
3            |1
3            |2
3            |4
4            |5
4            |6

meals_to_ingredients - contains ingredients (which may contain sub-ingredients) for each meal

meal_id|mapped_ingredient_id
1      |1
2      |2
3      |4

To get sub-ingredients (if any) for specified ingredient (let's say #3 - Fancy Sauce), I use:

WITH RECURSIVE
cte AS ( SELECT *
         FROM ingredients_to_ingredients 
         WHERE ingredient_id = 3
       UNION ALL
         SELECT ingredients_to_ingredients.*
         FROM ingredients_to_ingredients
         JOIN cte ON cte.mapped_ingredient_id = ingredients_to_ingredients.ingredient_id )
SELECT ingredients.ingredient_name
FROM cte
JOIN ingredients ON cte.mapped_ingredient_id = ingredients.ingredient_id;

And get the list:

Water
Salt
Spices
Pepper
Chili

Working demo - https://dbfiddle.uk/?rdbms=mariadb_10.4&fiddle=0303d2ae8cded77053d87a0f31d9c374

Often I need to fetch sub-ingredients of multiple ingredients stored on other table - meals_to_ingredients. After a day of re-writing query, I was able to achieve this:

  • Query works indefinitely
  • Query returns errors
  • Query returns 0 records
  • Query returns absolutely all records

How do I rewrite query so it returns ingredients (and sub-ingredients) of let's say two random meals? I can post links to my non-working examples of modified query at DB Fiddle if needed.

Edit: Updated with desired output. Let's say new query randomly selects meals #1 and #3.

Meal #1 has mapped ingredients #1, #2 (meals_to_ingredients table), and these ingredients have no sub-ingredients (no records in ingredients_to_ingredients table)

Meal #3 has mapped ingredient #3 (meals_to_ingredients table), and this ingredient has sub-ingredients #1, #2, #4 (ingredients_to_ingredients table), while sub-ingredient #4 itself has further sub-ingredients #5, #6 (ingredients_to_ingredients table again).

So the result of all ingredients should be:

Water (ingredient_id - 1)
Salt (ingredient_id - 2)
Fancy Sauce (ingredient_id - 3)
Water (ingredient_id - 1)
Salt (ingredient_id - 2)
Spices (ingredient_id - 4)
Pepper (ingredient_id - 5)
Chili (ingredient_id - 6)

In fact, I will only need a unique list of ingredients, but I have no problems writing a query which filters duplicated records, so the example result above includes all the ingredients for easier understanding how query should work.

CodePudding user response:

Look at this:

WITH RECURSIVE
cte AS ( 
    SELECT meal_id, mapped_ingredient_id ingredient_id
    FROM meals_to_ingredients
  UNION ALL
    SELECT cte.meal_id, iti.mapped_ingredient_id
    FROM cte
    JOIN ingredients_to_ingredients iti USING (ingredient_id)
)
SELECT cte.meal_id, ingredient_id, i.ingredient_name
FROM cte
JOIN ingredients i USING (ingredient_id)
-- WHERE cte.meal_id IN (1, 3)
ORDER BY 1,2

https://dbfiddle.uk/?rdbms=mariadb_10.4&fiddle=ee26da089c9bb2e5046fea0bc29041ff

  • Related