我有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
答案 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)
您的问题源于您没有规范化的数据模型。
你应该重新设计成这样的东西:
食物表:
INGREDIENTS表:
FOOD2INGREDIENTS表:
一旦进行了这样的重新设计,你就可以通过查询得到你想要的东西:
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'
)
但是,我认为JacobM和Kerbocat在数据库重新设计时是正确的想法,并且您认为数据库设计有问题需要受到赞扬。请注意,如果您需要具有4种(或更多)成分的配方,您将面临当前设计的灾难(例如,因为您必须编辑包括多路UNION操作的所有现有SQL,如上所示),但重新设计的模式甚至都没有注意到。