所以,由于设计我的数据库,我很头疼。我列出了含有其成分的饮料,即:
name:Tea
ingredient1:teabag
ingredient2:water
name:Glass of water
ingredient1:water
name:Frozen Tea
ingredient1:ice
ingredient2:teabag
ingredient3:water
因此,正如您所看到的,列数可能会有所不同,每种成分的索引也是如此。这是唯一的例子,数据库可能包含大约100-1000行。你能帮我讲一下设计我的数据库的最好(或者只是一个好的)方法吗?我必须能够根据一些或每种成分进行选择,因此选择成分=水的位置给出3个结果(但在这种情况下,我必须发送三次查询)。我真的不知道如何使它工作正常
答案 0 :(得分:3)
我会创建三个表:Drink
,Ingredient
和DrinkIngredients
。从那里你可以根据需要在DrinkIngredients
表中插入许多成分。
以下是一个例子(请记住,这是为SQL Server编写的,因为我的MySQL知识有限)
Create Table Drink
(
DrinkId Int Not Null Identity(1,1) Primary Key,
Name Varchar (30) Null
)
Create Table Ingredient
(
IngredientId Int Not Null Identity(1,1) Primary Key,
Name Varchar (30) Null
)
Create Table DrinkIngredients
(
DrinkId Int Not Null,
IngredientId Int Not Null
)
Alter Table DrinkIngredients Add Constraint FK_DrinkIngredients_DrinkId Foreign Key (DrinkId) References Drink (DrinkId)
Alter Table DrinkIngredients Add Constraint FK_DrinkIngredients_IngredientId Foreign Key (IngredientId) References Ingredient (IngredientId)
Insert Drink (Name) Values ('Tea'), ('Glass of Water'), ('Frozen Tea')
Insert Ingredient (Name) Values ('Ice'), ('Tea bag'), ('Water')
Insert DrinkIngredients (DrinkId, IngredientId)
Values (1, 2), (1, 3), (2, 3), (3, 1), (3, 2), (3, 3)
Select D.Name As Drink, I.Name As Ingredient
From DrinkIngredients DI
Join Drink D On D.DrinkId = DI.DrinkId
Join Ingredient I On I.IngredientId = DI.IngredientId
Where D.Name = 'Frozen Tea'
您可以使用上一个查询查询数据,以查看指定名称的所有成分。这应该给你一个不错的起点。
答案 1 :(得分:2)
使用成分列的数据库设计称为非标准化。通常应避免使用非规范化的数据库结构,因为它们难以维护和使用。
而是使用两个表:一个“饮料”表和一个“成分”表。
CREATE TABLE Drink (
DrinkID INT AUTO_INCREMENT NOT NULL,
Name VARCHAR(50) NOT NULL,
PRIMARY KEY (DrinkID)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE Ingredient (
IngredientID INT AUTO_INCREMENT NOT NULL,
DrinkID INT NOT NULL,
Name VARCHAR(50) NOT NULL,
PRIMARY KEY (IngredientID),
INDEX IX_DrinkID (DrinkID),
FOREIGN KEY (DrinkID)
REFERENCES Drink(DrinkID)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
现在您插入如下记录:
INSERT INTO Drink (Name) VALUES ('Tea');
INSERT INTO Drink (Name) VALUES ('Glass of water');
INSERT INTO Drink (Name) VALUES ('Frozen Tea');
假设自动生成的DrinkID为1,2和3
INSERT INTO Ingredient (DrinkID, Name) VALUES (1, 'teabag');
INSERT INTO Ingredient (DrinkID, Name) VALUES (1, 'water');
INSERT INTO Ingredient (DrinkID, Name) VALUES (2, 'water');
INSERT INTO Ingredient (DrinkID, Name) VALUES (3, 'ice');
INSERT INTO Ingredient (DrinkID, Name) VALUES (3, 'teabag');
INSERT INTO Ingredient (DrinkID, Name) VALUES (3, 'water');
您可以返回含有水的饮料及其成分列表
SELECT
d.Name AS drink_name, i.Name AS ingredient_name
FROM
Drink d
INNER JOIN Ingredient i
ON d.DrinkID = i.DrinkID
WHERE
i.Name = 'water'
ORDER BY
d.Name, i.Name
或者,如果您只想要饮料
SELECT
Name
FROM
Drink
WHERE
DrinkID IN (
SELECT DrinkID
FROM Ingredient
WHERE Name = 'water'
)
ORDER BY
Name
您可以将子查询中的WHERE子句更改为WHERE Name IN ('water', 'wodka', 'ice')
。这将返回所有含有至少一种这些成分的饮料。
如果您需要查找具有所有这些成分的饮品,您必须将查询更改为
SELECT
d.Name
FROM
Drink d
INNER JOIN Ingredient i
ON d.DrinkID = i.DrinkID
WHERE
i.Name IN ('water', 'wodka', 'ice')
GROUP BY
d.Name
HAVING
COUNT(*) = 3
ORDER BY
d.Name