规范化的MySQL Pivot / Rows到没有唯一名称的列

时间:2015-02-03 05:28:23

标签: php mysql sql pivot-table

我似乎碰壁试图找出以下数据库的适当查询(简化):

'用户'表

userID    userName
1         John
2         Jane

'配料'表

注意:此表格会相当大!

ingredientID     ingredientName     ingredientImage
1                Tomatoes           tomato.png
2                Onions             onion.png
3                Red Pepper         redPepper.png

'食谱'表

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'表

注意:每个配方最多只能有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

我需要什么

我希望能够进行查询以列出所有食谱,并且每行会给我以下数据。

  • RecipeID
  • RecipeName中
  • RecipeDescription
  • 用户ID
  • 用户名
  • Ingredient1
  • Ingredient1Amount
  • Ingredient2
  • Ingredient2Amount
  • Ingredient3
  • Ingredient3Amount
  • Ingredient4
  • Ingredient4Amount
  • Ingredient5
  • Ingredient5Amount
  • 注意:只能达到Ingredient5,因为配方最多只能有5种成分

我正在寻找的样本

  • (1,'番茄酱','我的自制番茄酱',1,' John','番茄',&# 39; 3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
  • (1,' Salsa',' Spicy salsa',1,' John',' Tomatoes',2,&#39 ;洋葱',1,NULL,NULL,NULL,NULL,NULL,NULL)
  • (1,' Bruschetta Topping',' Onion and Tomato Topping',2,' Jane',' Tomatoes',2, ' Onions',1,' Red Pepper',2,NULL,NULL,NULL,NULL)

我以表格格式寻找的样本

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所示)但似乎无法解决这种情况,因为成分列表将结束非常大(在示例中的主题是一个非常小的集合)。

修改 这是什么最好的做法?我看到拉动配方然后做一个嵌套循环拉动成分会更简单,但这似乎很密集,特别是如果用户数量太大。我也考虑过对表格进行去标准化,但我需要对未来的分析/统计数据进行标准化,以解决潜在的问题,例如:有多少食谱使用西红柿或其他类似的东西。

TL; DR

我有规范化的表格,我希望将其放入一行显示给用户,并且' MAX(CASE ...'解决方案对我不起作用,因为数据集将非常大

1 个答案:

答案 0 :(得分:0)

以下是使用多个LEFT JOIN的示例。加入用户非常简单。加入成分有点复杂,因为你必须首先加入RecipeIngredients表,然后使用该id加入成分。 (注意这只有前2个成分,下一个/后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