我想创建一个网站,允许客户从该网站订购食物。
食物有两种:
如果他们从列表中选择披萨-他们可能需要选择基本(薄皮,深皮),其他和披萨尺寸/选项。
在这种情况下如何设计表格?
注意:每个项目都有1个或更多选项。一个选项可能有额外的(1个或更多)或没有额外的。如果项目是披萨型-那么它可能有底料( shell )
屏幕截图原型(prototype)
看到我正在尝试实现的两个屏幕截图,我在数据库设计的正确路径上还是可以做得更好?
披萨定制:
牛肉汉堡定制:
附加功能(下拉/勾选框)
在临时演员上,有时我需要为下拉菜单而不是复选框添加多个额外演员。这意味着客户只能从1、2或3个下拉菜单中选择1个。
数据库设计
您将如何设置数据库模型以实现类似上述自定义选项的内容?
这是我想出的:
类别表:
+----------+--------------+------+-----+---------+----------------+
| 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 =普通,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 | |
+-------------+--------------+------+-----+---------+----------------+
item_extras表:
(您是否认为应该为披萨toppin和其他设置单独的表格?)
+-----------+--------------+------+-----+---------+----------------+
| 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 |
正如您可以在一张桌子上看到的汉堡和披萨的额外内容..应该分开吗?
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。每个披萨也会有不同的额外费用。
数据库设计正确还是可以改进的?
最佳答案
如果需要进行下拉菜单,请将下拉菜单的值放在表中。
只要可以在下拉菜单中轻松分离出所需的值,就可以在其中放置其他值。
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)是而不是唯一,则您的数据未规范化,则您做错了。
因为您使用大量联接,所以IMHO最好使用InnoDB,它具有一些很酷的功能来加快使用大量PK的联接。
无论人们怎么说
在缓慢开始之前,请不要反常态化。
使用索引
在所有名为* _id的字段上添加索引。
还要在
where
子句中经常使用的alls字段上添加索引。请勿将索引放在基数较低的字段上,因此不要在 bool(boolean) 或枚举字段上添加索引!
索引减慢插入速度并加快选择速度。