无限加入同一个 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
包含其他子成分(Pepper
和 Chili
),我也需要列出它们。
有人会说我可以添加第二个子查询,但有一个问题:没有固定的数字。换句话说,一种成分可能根本没有子成分,而另一种成分可能有很多子成分(这需要几十个子查询)。
如何编写一个查询,只要任何成分都有子成分,它就会一直选择映射的子成分?现在,我只是使用了很多重复的子查询(比如几十个,只是为了确保包含所有可能的子子子成分),但查询看起来很难看,我相信这不是最好的方法。
对如何修改上面的查询有什么建议吗?
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
我什至不知道如何正确命名这个问题。我知道如何加入相同的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
包含其他子成分(Pepper
和 Chili
),我也需要列出它们。
有人会说我可以添加第二个子查询,但有一个问题:没有固定的数字。换句话说,一种成分可能根本没有子成分,而另一种成分可能有很多子成分(这需要几十个子查询)。
如何编写一个查询,只要任何成分都有子成分,它就会一直选择映射的子成分?现在,我只是使用了很多重复的子查询(比如几十个,只是为了确保包含所有可能的子子子成分),但查询看起来很难看,我相信这不是最好的方法。
对如何修改上面的查询有什么建议吗?
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