SQL数据库模型:FOOD和INGREDIENTS表

时间:2012-06-17 18:17:07

标签: sql

我有2张桌子:食物和成分。我想选择制作某种食物所需的所有成分。

我以为我可以这样做:

select NAME from INGREDIENTS
 where ID in (select ING1_ID, ING2_ID, ING3_ID from FOOD where NAME = 'Meat soup')

这显然不起作用,因为我需要在“in”子选择查询中传递一串逗号分隔的ID。我正在研究将列值列表转换为字符串,并且有一些解决方案,但我开始认为我可能过于复杂,我的数据库模型是错误的。

食物表:

ID      | NAME          | ING1_ID  | ING2_ID  | ING3_ID
--------+---------------+----------+----------+--------
1       | Meat soup     | 1        | 2        | 3
2       | Pasta Bolo    | 3        | 4        | 5
3       | Chicken salad | 2        | 4        | 5

成分表:

ID      | NAME          
--------+-----------
1       | pasta     
2       | onion   
3       | oil 
4       | paprika 
5       | chicken 
6       | cucumber 

3 个答案:

答案 0 :(得分:7)

许多菜肴含有三种以上的成分,当您搜索时,您不关心给定的成分是#1还是#2或#3。

所以更好的模型是

FOOD
id | name
1  | meat soup


INGREDIENTS
id | name 
1  | meat  

FOOD_INGREDIENTS
food_id | ingredients_id
1       | 1

现在您的查询只是

select i.name from ingredients i, food f, food_ingredients fi
where fi.food_id = f.id
and fi.ingredients_id = i.id
and f.name = "meat soup"

“food_ingredients”表通常称为“连接表”。关于连接表的另一个好处是,您可以添加特定于某种食物中特定包含成分的信息(例如量,或者应该如何准备)。

答案 1 :(得分:3)

您的问题源于您没有规范化的数据模型。

你应该重新设计成这样的东西:

食物表:

  • FoodID
  • 名称

INGREDIENTS表:

  • IngID
  • 名称

FOOD2INGREDIENTS表:

  • FoodID
  • IngID
  • (在这里添加数量会很有意义)

一旦进行了这样的重新设计,你就可以通过查询得到你想要的东西:

SELECT i.ID, I.Name 
FROM Ingredients I 
 INNER JOIN Food2Ingredients F2I 
 ON I.IngID = F2I.IngID
WHERE
  F2I.FoodID = :foodid;

答案 2 :(得分:2)

只要您的所有食谱都非常贫乏以至于只需要三种成分,那么您可以通过以下方式解决原始查询的问题:

SELECT Name FROM Ingredients
 WHERE ID IN (SELECT ING1_ID FROM Food WHERE Name = 'Meat soup'
              UNION
              SELECT ING2_ID FROM Food WHERE Name = 'Meat soup'
              UNION
              SELECT ING3_ID FROM Food WHERE Name = 'Meat soup'
             )

但是,我认为JacobMKerbocat在数据库重新设计时是正确的想法,并且您认为数据库设计有问题需要受到赞扬。请注意,如果您需要具有4种(或更多)成分的配方,您将面临当前设计的灾难(例如,因为您必须编辑包括多路UNION操作的所有现有SQL,如上所示),但重新设计的模式甚至都没有注意到。