mysql - 比萨与食品 - 数据库设计

标签 mysql sql database database-design relational-database

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

有两种食物类型:

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

如果他们从列表中选择比萨 - 他们可能需要选择基础(薄皮、去皮)、附加和比萨大小/选项。

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

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

截图原型(prototype)

看看我正在尝试实现的两个屏幕截图,我在数据库设计上走在了正确的道路上,或者还有什么可以做得更好?

披萨定制:

GUI-Mockup to customize pizza

牛肉汉堡定制:

GUI-Mockup for the burger options

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

关于额外功能,有时我需要为下拉菜单添加多个额外功能而不是复选框。这意味着客户只能从 1、2 或 3 个下拉菜单中选择 1 个。

GUI-Mockup extra dropdowns

数据库设计

您将如何设置您的数据库模型来实现类似上述自定义选项的功能? 这是我想出的:

类别表:

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

项目表:

+-----------+--------------+------+-----+---------+----------------+
| 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    |                |
+-----------+--------------+------+-----+---------+----------------+

- item_type (0 = normal, 1 = pizza, 2 = set meal)

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    |                |
+-------------+--------------+------+-----+---------+----------------+

item_extras 表: (你认为应该为比萨托平和额外的东西有单独的 table 吗?)

+-----------+--------------+------+-----+---------+----------------+
| 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    |                |
+-----------+--------------+------+-----+---------+----------------+

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    |                |
+-----------+--------------+------+-----+---------+----------------+

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 |

如您所见,一张 table 上有汉堡和披萨的附加品。应该分开吗?

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 |
+---------+-----------+------------+------+

请记住,每件商品的额外价格并不总是相同。例如:尺寸为 10 英寸的比萨饼每多出一个,需支付 1.00 美元,但尺寸为 12 英寸的比萨饼则需支付 0.50 美元。此外,每个披萨都会有不同的额外费用。

数据库设计是否正确或有待改进?

最佳答案

Im stuck with Extras functionality - how to design table and fields for the dropdown extras? See my question "Extras functionality (Dropdown / tickboxes)"

如果您需要制作下拉菜单,请将下拉菜单的值放在表格中。
可以在其中放置额外的值,只要您可以轻松地在下拉列表中分离出您需要的值。

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)

一旦您知道该项目,您就可以使用以下方法填充下拉列表:

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'

规范化这些表
此表有一个重大缺陷:

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 |
+----------+-----------+-----------+------+

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

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

不管别人怎么说
在缓慢开始之前不要反规范化。

使用索引
在所有名为 *_id 的字段上放置索引。
还要在 where 子句中经常使用的 alls 字段上放置索引。
不要将索引放在基数较低的字段上,因此不要在 bool 或枚举字段上设置索引!
索引会减慢插入速度并加快选择速度。

关于mysql - 比萨与食品 - 数据库设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7284687/

相关文章:

sql - 强制 SQL Server 删除数据库

mysql - 在日期时间列中插入值时出错

sql - postgresql 迭代n条记录

sql - 查询同时事件的最大数量

sql - 根据时间合并两个表

php - 管理连接表的最佳方法

java - 来自数据库的动态 Java 对象,包含字段、值和数据类型

MySQL 缓慢改变维度 SCD2 + ON DUPLICATE KEY UPDATE

mysql - Mysql中如何查询排除条件行

mysql - 保存具有宽度和高度的 Blob 图像 VB.Net、MySQL