无限加入同一个 table 直到存在

Unlimited join to the same table until exists

我什至不知道如何正确命名这个问题。我知道如何加入相同的table,但这种情况略有不同。我会尽量让一切变得简单。这里有 2 tables:

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

我需要获取指定成分的所有子成分(如果有)。所以如果我想获得#3(花式酱)的子成分,我使用:

SELECT * FROM ingredients AS main
LEFT JOIN ingredients_to_ingredients AS sub
ON main.ingredient_id=sub.ingredient_id 
LEFT JOIN ingredients
ON sub.mapped_ingredient_id=ingredients.ingredient_id
WHERE main.ingredient_id=3

并获取列表:

Water
Salt
Spices

简单。但如您所见,Spices 包含其他子成分(PepperChili),我也需要列出它们。

有人会说我可以添加第二个子查询,但有一个问题:没有固定的数字。换句话说,一种成分可能根本没有子成分,而另一种成分可能有很多子成分(这需要几十个子查询)。

如何编写一个查询,只要任何成分都有子成分,它就会一直选择映射的子成分?现在,我只是使用了很多重复的子查询(比如几十个,只是为了确保包含所有可能的子子子成分),但查询看起来很难看,我相信这不是最好的方法。

对如何修改上面的查询有什么建议吗?

P.S。我敢肯定有人会说使用映射到自身的 sub-sub-sub 成分是一个糟糕的设计。好吧,我不能对餐厅负责人说——“不要在你的配料中使用次级配料,因为从数据库的角度来看,这是糟糕的设计”。希望您了解为什么设计保持原样且无法更改。

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;

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