Pizza&Food - 数据库设计

I'l*_*ack 18 mysql sql database database-design relational-database

我想创建一个网站,允许客户从网站订购食物.

有两种食物类型:

  • 常规食品/饮料(例如:汉堡,烤肉串,薯片,可乐,百事可乐等)
  • 比萨食品(例如:Margherita Pizza,肉类比萨饼等)

如果他们从列表中选择披萨 - 他们可能需要选择Base(薄皮,脱壳),Extras和披萨大小/选项.

在这种情况下如何设计表格?

注意:每个项目都有1个或更多选项.一个选项可能有额外的(1或更多)或没有额外的.如果项目是披萨类型 - 那么它可能有基地(地壳)

截图原型

看到我试图实现的两个截图,我在数据库设计的正确路径上或者哪些可以做得更好?

比萨定制:

GUI-Mockup自定义披萨

牛肉汉堡定制:

汉堡选项的GUI-Mockup

额外功能(下拉/复选框)

在附加内容上,有时我需要为下拉列表添加多个额外内容而不是tickbox.这意味着客户只能从1个,2个或3个下拉菜单中选择1个.

GUI-Mockup额外下拉菜单

数据库设计

您将如何设置数据库模式以实现上述自定义选项?这是我想出的:

类别表:

+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| cat_id   | int(11)      | NO   | PRI | NULL    | auto_increment |
| cat_name | varchar(100) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

物品表:

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| item_id   | int(11)      | NO   | PRI | NULL    | auto_increment |
| cat_id    | int(11)      | NO   |     | NULL    |                |
| item_name | varchar(100) | NO   |     | NULL    |                |
| item_type | int(11)      | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

- item_type(0 =正常,1 =披萨,2 =套餐)

item_options表:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| option_id   | int(11)      | NO   | PRI | NULL    | auto_increment |
| item_id     | int(11)      | NO   |     | NULL    |                |
| option_name | varchar(100) | NO   |     | NULL    |                |
| price       | decimal(6,2) | NO   |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

item_extras表:( 您认为应该有单独的表来进行披萨toppin和extras?)

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| extra_id  | int(11)      | NO   | PRI | NULL    | auto_increment |
| option_id | int(11)      | NO   |     | NULL    |                |
| name      | varchar(50)  | NO   |     | NULL    |                |
| cost      | decimal(6,2) | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

item_pizza_base表:

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| base_id   | int(11)      | NO   | PRI | NULL    | auto_increment |
| option_id | int(11)      | NO   |     | NULL    |                |
| base_name | varchar(50)  | NO   |     | NULL    |                |
| cost      | decimal(6,2) | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

SQL结果:

mysql> select * from categories;
+--------+----------+
| cat_id | cat_name |
+--------+----------+
|      1 | Pizzas   |
|      2 | Burgers  |

mysql> select * from items;
+---------+--------+------------------+-----------+
| item_id | cat_id | item_name        | item_type |
+---------+--------+------------------+-----------+
|       1 |      1 | Vegetarian Pizza |         1 |
|       2 |      2 | Beef Burger      |         0 |

mysql> select * from item_options;
+-----------+---------+-------------+-------+
| option_id | item_id | option_name | price |
+-----------+---------+-------------+-------+
|         1 |       1 | 12 Inches   |  5.60 |
|         2 |       1 | 14 Inches   |  7.20 |
|         3 |       2 | 1/4lb       |  1.80 |
|         4 |       2 | 1/2lb       |  2.50 |

mysql> select * from item_extras;
+----------+-----------+-----------+------+
| extra_id | option_id | name      | cost |
+----------+-----------+-----------+------+
|        1 |         1 | Mushroom  | 1.00 |
|        2 |         1 | Pepperoni | 1.00 |
|        3 |         2 | Mushroom  | 1.00 |
|        4 |         2 | Pepperoni | 1.00 |
|        5 |         3 | Chips     | 0.50 |
|        6 |         4 | Chips     | 0.50 |
Run Code Online (Sandbox Code Playgroud)

正如你可以在1张桌子上看到汉堡包和披萨的额外内容......它应该分开吗?

mysql> select * from item_pizza_base;
+---------+-----------+------------+------+
| base_id | option_id | base_name  | cost |
+---------+-----------+------------+------+
|       1 |         1 | Thin Crust | 0.00 |
|       2 |         1 | Deep Crust | 0.00 |
|       3 |         2 | Thin Crust | 0.00 |
|       4 |         2 | Deep Crust | 0.00 |
+---------+-----------+------------+------+
Run Code Online (Sandbox Code Playgroud)

请记住,每个项目的额外费用并不总是相同.例如:比萨尺寸10"每增加1美元,但12英寸比萨增加0.50美元.还有一个案例,每个披萨将有不同的额外费用.

数据库设计是正确的还是可以改进的?

Joh*_*ica 8

我坚持使用Extras功能 - 如何为下拉附加设计表格和字段?看到我的问题"额外功能(下拉/勾选)"

如果您需要下拉列表,请将下拉列表的值放在表格中.
只要您可以轻松地在下拉列表中分离出所需的值,就可以在其中添加额外的值.

Example

table option_labels
-------------------
id    integer auto_increment PK
name  varchar(40)

table toppings
--------------
id               integer  auto_increment PK
option_label_id  integer  foreign key references option_labels(id)
item_id          integer  foreign key references items(item_id)
price            decimal(10,2)
Run Code Online (Sandbox Code Playgroud)

只要您知道该项目,就可以使用以下命令填充下拉列表:

SELECT ol.name, t.price FROM toppings t
INNER JOIN option_labels ol ON (t.option_label_id = ol.id)
WHERE t.item_id = '$item_id'
Run Code Online (Sandbox Code Playgroud)

规范化这些表
这个表有一个主要缺陷:

mysql> select * from item_extras;
+----------+-----------+-----------+------+
| extra_id | option_id | name      | cost |
+----------+-----------+-----------+------+
|        1 |         1 | Mushroom  | 1.00 |
|        2 |         1 | Pepperoni | 1.00 |
|        3 |         2 | Mushroom  | 1.00 |
|        4 |         2 | Pepperoni | 1.00 |
|        5 |         3 | Chips     | 0.50 |
|        6 |         4 | Chips     | 0.50 |
+----------+-----------+-----------+------+
Run Code Online (Sandbox Code Playgroud)

它没有标准化,将名称放在单独的标签表中,就像上面的例子一样.如果一行(不包括id)不是唯一的,那么您的数据不会被标准化并且您做错了.

因为你使用了很多连接,所以恕我直言最好使用InnoDB,它有一些很酷的功能来加速使用PK的连接很多.

无论人们说什么,
在慢慢开始之前不要反规范化.

使用索引
在名为*_id的所有字段上放置索引.
where经常在子句中使用的alls字段上放置一个索引.
不要在具有低基数的字段上放置索引,因此在布尔或枚举字段上没有索引!
索引会减慢插入速度并加快选择速度.


Gre*_*mer 5

您有一个订单表。然后是订单商品或订单行表。对于可以带有配料的物品,您最终会得到一个存放配料的桌子。特别是披萨,您不必担心一半,所以人们可以在每一半上订购不同的东西。到目前为止,您似乎正在朝着正确的方向前进。

设计过程中,我首先要弄清楚“对象”。有无形的物体,如汉堡或披萨,有无形的物体,如订单,订单行。

必胜客拥有在网上设置匹萨的最佳用户界面之一。我会看一下,因为它将为您提供有关如何存储数据的一些想法。