使用来自其他 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个错误
- 查询returns0条记录
- 查询returns绝对所有记录
如何重写查询,以便 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
问题与
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个错误
- 查询returns0条记录
- 查询returns绝对所有记录
如何重写查询,以便 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