数据库设计,不同列中的许多不同项目(项目 a 可以在列 a 或 b 中)
Database design, many different items in different columns (item a can be in column a or b)
所以,为了设计我的数据库,我很头疼。我有饮料清单及其成分,即:
name:Tea
ingredient1:teabag
ingredient2:water
name:Glass of water
ingredient1:water
name:Frozen Tea
ingredient1:ice
ingredient2:teabag
ingredient3:water
因此,如您所见,列数可能会有所不同,每种成分的索引也会有所不同。这只是示例,数据库可能包含大约 100-1000 行。您能帮我说说设计数据库的最佳(或最佳)方法吗?我必须能够 select 基于某些或每一种成分,所以 select 其中成分=水给出 3 个结果(但在这种情况下我必须发送查询三次)。我真的不知道如何让它正常工作
将列用于成分的数据库设计称为非规范化。通常应避免使用非规范化数据库结构,因为它们难以维护和使用。
而是使用两个 table:一个 "Drink" table 和一个 "Ingredient" table.
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');
您可以 return 一份包含水及其成分的饮料清单,如下所示
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')
。这 return 为您提供至少包含其中一种成分的所有饮料。
如果您需要查找包含所有这些成分的饮料,您必须将查询更改为
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
我会创建三个 table:Drink
、Ingredient
和 DrinkIngredients
。您可以从那里向 DrinkIngredients
table 添加任意数量的成分。
这是一个例子(请记住,这是为 SQL 服务器编写的,因为我的 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'
您可以使用上次查询来查询数据,以查看指定名称的所有成分。这应该会给你一个不错的起点。
所以,为了设计我的数据库,我很头疼。我有饮料清单及其成分,即:
name:Tea
ingredient1:teabag
ingredient2:water
name:Glass of water
ingredient1:water
name:Frozen Tea
ingredient1:ice
ingredient2:teabag
ingredient3:water
因此,如您所见,列数可能会有所不同,每种成分的索引也会有所不同。这只是示例,数据库可能包含大约 100-1000 行。您能帮我说说设计数据库的最佳(或最佳)方法吗?我必须能够 select 基于某些或每一种成分,所以 select 其中成分=水给出 3 个结果(但在这种情况下我必须发送查询三次)。我真的不知道如何让它正常工作
将列用于成分的数据库设计称为非规范化。通常应避免使用非规范化数据库结构,因为它们难以维护和使用。
而是使用两个 table:一个 "Drink" table 和一个 "Ingredient" table.
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');
您可以 return 一份包含水及其成分的饮料清单,如下所示
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')
。这 return 为您提供至少包含其中一种成分的所有饮料。
如果您需要查找包含所有这些成分的饮料,您必须将查询更改为
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
我会创建三个 table:Drink
、Ingredient
和 DrinkIngredients
。您可以从那里向 DrinkIngredients
table 添加任意数量的成分。
这是一个例子(请记住,这是为 SQL 服务器编写的,因为我的 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'
您可以使用上次查询来查询数据,以查看指定名称的所有成分。这应该会给你一个不错的起点。