使用来自其他 table 的 where 子句递归连接到相同的 table

Recursive join to the same table using where clause from additional table

问题与 有关,但为查询带来了额外的 table。表:

ingredients - 包含成分 ID 和名称

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

ingredients_to_ingredients - 包含每种成分的可选子成分

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

meals_to_ingredients - 包含每餐的成分(可能包含次成分)

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

要获取指定成分(比如#3 - Fancy Sauce)的子成分(如果有的话),我使用:

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;

并获取列表:

Water
Salt
Spices
Pepper
Chili

工作演示 - https://dbfiddle.uk/?rdbms=mariadb_10.4&fiddle=0303d2ae8cded77053d87a0f31d9c374

我经常需要获取存储在其他 table - meals_to_ingredients 上的多种成分的子成分。经过一天的重写查询,我实现了这个:

如何重写查询,以便 returns 比方说两顿随机餐的配料(和次配料)?如果需要,我可以 post 链接到我在 DB Fiddle 修改查询的非工作示例。

编辑:更新了所需的输出。假设新查询随机选择膳食 #1 和 #3。

第 1 餐已映射成分 #1、#2 (meals_to_ingredients table),并且这些成分没有子成分(ingredients_to_ingredients [=73= 中没有记录])

第 3 餐已映射成份 #3 (meals_to_ingredients table),此成份包含子成份 #1、#2、#4 (ingredients_to_ingredients table),而子成分 #4 本身还有其他子成分 #5、#6(ingredients_to_ingredients table)。

所以所有成分的结果应该是:

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)

事实上,我只需要一个唯一的成分列表,但我编写一个过滤重复记录的查询没有问题,所以上面的示例结果包含所有成分,以便更容易理解查询应该如何工作。

看看这个:

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