规范化 MySQL 将数据透视/行转换为没有唯一名称的列
Normalized MySQL Pivot / Rows to Columns without unique names
我在尝试为以下数据库(简化版)找出合适的查询时似乎碰壁了:
'Users' Table
userID userName
1 John
2 Jane
'Ingredients' Table
注意:这个 table 会变得相当大!
ingredientID ingredientName ingredientImage
1 Tomatoes tomato.png
2 Onions onion.png
3 Red Pepper redPepper.png
'Recipes' Table
recipeID userID recipeName description
1 1 Tomato Sauce My homemade tomato sauce
2 1 Salsa Spicy Salse
3 2 Bruschetta Onion and Tomato Topping!
'RecipeIngredients' Table
注意:每个配方最多只能有 5 种成分,这将在创建配方(插入期间)时受到限制
recipeIngredientID recipeID ingredientID amount
1 1 1 3
2 2 1 2
3 2 2 1
4 3 1 2
4 3 2 1
4 3 3 2
我需要什么
我希望能够执行查询以列出所有食谱,并为我提供每行以下数据。
- 配方ID
- 食谱名称
- 食谱描述
- 用户ID
- 用户名
- 成分 1
- 成分1数量
- 成分 2
- 成分2数量
- 成分 3
- 成分3数量
- 成分 4
- 成分4数量
- 成分 5
- 成分5数量
- 注意:最多只能使用成分 5,因为食谱最多只能包含 5 种成分
我正在寻找的示例
- (1, 'Tomato Sauce', 'My homemade tomato sauce', 1, 'John', 'Tomatoes', '3', NULL, NULL, NULL, NULL, NULL, NULL,空,空)
- (1, 'Salsa', 'Spicy salsa', 1, 'John', 'Tomatoes', 2, 'Onions', 1, NULL, NULL, NULL,空,空,空)
- (1, 'Bruschetta Topping', 'Onion and Tomato Topping', 2, 'Jane', 'Tomatoes', 2, 'Onions', 1, 'Red Pepper', 2, 空, 空, 空, 空)
我正在寻找的 table 格式的示例
RecipeID RecipeName RecipeDescription UserID UserName Ingredient1 Ingredient1Image Ingredient1Amount Ingredient2 IIngredient1Image Ingredient2Amount Ingredient3 Ingredient1Image Ingredient3Amount Ingredient4 Ingredient1Image Ingredient4Amount Ingredient5 Ingredient1Image Ingredient5Amount
1 Tomato Sauce My homemade tomato sauce 1 John Tomatoes tomato.png 3 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
2 Salsa Spicy salsa 1 John Tomatoes tomato.png 2 Onions onion.png 1 NULL NULL NULL NULL NULL NULL NULL NULL NULL
3 Bruschetta Onion and Tomato Topping 2 Jane Tomatoes tomato.png 2 Onions onion.png 1 Red Pepper redPepper.png 2 NULL NULL NULL NULL NULL NULL
帮助
如有任何帮助,我们将不胜感激。我已经查看了 'MAX(CASE ...' 语句(如此处所示 https://dba.stackexchange.com/questions/47902/how-to-transpose-convert-rows-as-columns-in-mysql),但在这种情况下似乎不起作用,因为成分列表最终会非常大(示例中的主题是相当小的一组)。
编辑
这方面的最佳做法是什么?我看到拉出食谱然后做一个嵌套循环来拉出配料会更简单,但这似乎很密集,尤其是在用户数量太大的情况下。我还考虑过对 table 进行去规范化,但我需要为将来 analytics/statistics 对数据进行规范化,以解决潜在的问题,例如:有多少食谱使用西红柿或类似的东西。
TL;DR
我已经规范化了 tables,我想在一行中显示给用户,'MAX(CASE...' 解决方案对我不起作用,因为数据集会非常大
这是一个使用多个 LEFT JOIN
的示例。加入用户非常简单。加入成分有点复杂,因为您必须先加入 RecipeIngredients
table,然后使用该 ID 加入成分。 (注意这只有前 2 个成分,next/last 3 个可以用同样的方法完成)
SELECT
r.recipeID, r.recipeName, r.description,
u.userID, u.userName,
I1.ingredientName as Ingredient1, I1.ingredientImage as Ingredient1Image, rI1.amount as Ingredient1Amount,
I2.ingredientName as Ingredient2, I2.ingredientImage as Ingredient2Image, rI2.amount as Ingredient2Amount
FROM
Recipes r
LEFT JOIN
Users u
ON
u.userID = r.userID
/*First Ingredient*/
LEFT JOIN
RecipeIngredients rI1
ON
rI1.recipeIngredientID = (
SELECT
rIa.recipeIngredientID
FROM RecipeIngredients rIa
WHERE rIa.recipeID = r.recipeID ORDER BY rIa.recipeIngredientID LIMIT 0,1 )
LEFT JOIN
Ingredients I1
ON
I1.ingredientID = rI1.ingredientID
/*Second Ingredient*/
LEFT JOIN
RecipeIngredients rI2
ON
rI2.recipeIngredientID = (
SELECT
rIb.recipeIngredientID
FROM RecipeIngredients rIb
WHERE rIb.recipeID = r.recipeID ORDER BY rIb.recipeIngredientID LIMIT 1,1 )
LEFT JOIN
Ingredients I2
ON
I2.ingredientID = rI2.ingredientID
这是一个有效的 sqlFiddle - http://sqlfiddle.com/#!2/3215e1/6
我在尝试为以下数据库(简化版)找出合适的查询时似乎碰壁了:
'Users' Table
userID userName
1 John
2 Jane
'Ingredients' Table
注意:这个 table 会变得相当大!
ingredientID ingredientName ingredientImage
1 Tomatoes tomato.png
2 Onions onion.png
3 Red Pepper redPepper.png
'Recipes' Table
recipeID userID recipeName description
1 1 Tomato Sauce My homemade tomato sauce
2 1 Salsa Spicy Salse
3 2 Bruschetta Onion and Tomato Topping!
'RecipeIngredients' Table
注意:每个配方最多只能有 5 种成分,这将在创建配方(插入期间)时受到限制
recipeIngredientID recipeID ingredientID amount
1 1 1 3
2 2 1 2
3 2 2 1
4 3 1 2
4 3 2 1
4 3 3 2
我需要什么
我希望能够执行查询以列出所有食谱,并为我提供每行以下数据。
- 配方ID
- 食谱名称
- 食谱描述
- 用户ID
- 用户名
- 成分 1
- 成分1数量
- 成分 2
- 成分2数量
- 成分 3
- 成分3数量
- 成分 4
- 成分4数量
- 成分 5
- 成分5数量
- 注意:最多只能使用成分 5,因为食谱最多只能包含 5 种成分
我正在寻找的示例
- (1, 'Tomato Sauce', 'My homemade tomato sauce', 1, 'John', 'Tomatoes', '3', NULL, NULL, NULL, NULL, NULL, NULL,空,空)
- (1, 'Salsa', 'Spicy salsa', 1, 'John', 'Tomatoes', 2, 'Onions', 1, NULL, NULL, NULL,空,空,空)
- (1, 'Bruschetta Topping', 'Onion and Tomato Topping', 2, 'Jane', 'Tomatoes', 2, 'Onions', 1, 'Red Pepper', 2, 空, 空, 空, 空)
我正在寻找的 table 格式的示例
RecipeID RecipeName RecipeDescription UserID UserName Ingredient1 Ingredient1Image Ingredient1Amount Ingredient2 IIngredient1Image Ingredient2Amount Ingredient3 Ingredient1Image Ingredient3Amount Ingredient4 Ingredient1Image Ingredient4Amount Ingredient5 Ingredient1Image Ingredient5Amount
1 Tomato Sauce My homemade tomato sauce 1 John Tomatoes tomato.png 3 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
2 Salsa Spicy salsa 1 John Tomatoes tomato.png 2 Onions onion.png 1 NULL NULL NULL NULL NULL NULL NULL NULL NULL
3 Bruschetta Onion and Tomato Topping 2 Jane Tomatoes tomato.png 2 Onions onion.png 1 Red Pepper redPepper.png 2 NULL NULL NULL NULL NULL NULL
帮助
如有任何帮助,我们将不胜感激。我已经查看了 'MAX(CASE ...' 语句(如此处所示 https://dba.stackexchange.com/questions/47902/how-to-transpose-convert-rows-as-columns-in-mysql),但在这种情况下似乎不起作用,因为成分列表最终会非常大(示例中的主题是相当小的一组)。
编辑 这方面的最佳做法是什么?我看到拉出食谱然后做一个嵌套循环来拉出配料会更简单,但这似乎很密集,尤其是在用户数量太大的情况下。我还考虑过对 table 进行去规范化,但我需要为将来 analytics/statistics 对数据进行规范化,以解决潜在的问题,例如:有多少食谱使用西红柿或类似的东西。
TL;DR
我已经规范化了 tables,我想在一行中显示给用户,'MAX(CASE...' 解决方案对我不起作用,因为数据集会非常大
这是一个使用多个 LEFT JOIN
的示例。加入用户非常简单。加入成分有点复杂,因为您必须先加入 RecipeIngredients
table,然后使用该 ID 加入成分。 (注意这只有前 2 个成分,next/last 3 个可以用同样的方法完成)
SELECT
r.recipeID, r.recipeName, r.description,
u.userID, u.userName,
I1.ingredientName as Ingredient1, I1.ingredientImage as Ingredient1Image, rI1.amount as Ingredient1Amount,
I2.ingredientName as Ingredient2, I2.ingredientImage as Ingredient2Image, rI2.amount as Ingredient2Amount
FROM
Recipes r
LEFT JOIN
Users u
ON
u.userID = r.userID
/*First Ingredient*/
LEFT JOIN
RecipeIngredients rI1
ON
rI1.recipeIngredientID = (
SELECT
rIa.recipeIngredientID
FROM RecipeIngredients rIa
WHERE rIa.recipeID = r.recipeID ORDER BY rIa.recipeIngredientID LIMIT 0,1 )
LEFT JOIN
Ingredients I1
ON
I1.ingredientID = rI1.ingredientID
/*Second Ingredient*/
LEFT JOIN
RecipeIngredients rI2
ON
rI2.recipeIngredientID = (
SELECT
rIb.recipeIngredientID
FROM RecipeIngredients rIb
WHERE rIb.recipeID = r.recipeID ORDER BY rIb.recipeIngredientID LIMIT 1,1 )
LEFT JOIN
Ingredients I2
ON
I2.ingredientID = rI2.ingredientID
这是一个有效的 sqlFiddle - http://sqlfiddle.com/#!2/3215e1/6