如何将多个表格与单个ID关联

3

我正在尝试创建一个使用PHP和MYSQL(与XAMPP一起)的数据库,其中存储有关各种快餐店及其分支机构的信息,以及他们在分支机构提供的菜单。我已经在我的数据库中创建了一些表,详细说明了快餐店、分支机构、菜单的类别和子类别以及它们在表中提供的项目。下面是表的摘录/样例:

Restaurants
+-------------+----------------+
| RestaurantID| RestaurantName | 
+-------------+----------------+
|     1       | PizzaHut       |
|     2       | BurgerKing     |
|     3       | KFC            | 
|     4       | SubWay         |
+-------------+----------------+

Branches
+---------------+----------------+
| RestaurantName| BranchAddress  | 
+---------------+----------------+
|   KFC         | XXX-1234       |
|   KFC         | AAA-1234       |
|   KFC         | YYY-1234       | 
|   BurgerKing  | DDD-1234       |
+---------------+----------------+

Categories
+---------------+----------------+
| BranchAddress | Categories     | 
+---------------+----------------+
|   XXX-1234    | Fries          |
|   AAA-1234    | Burgers        |
|   YYY-1234    | Drinks         | 
|   DDD-1234    | Burgers        |
+---------------+----------------+

SubCategories
+---------------+----------------+
| Categories    | SubCategories  | 
+---------------+----------------+
|   Fries       | Cheese         |
|   Burgers     | Chicken        |
|   Drinks      | Carbonated     | 
|   Burgers     | Beef           |
+---------------+----------------+

Items
+---------------+----------------+
| SubCategories | Items          | 
+---------------+----------------+
|   Cheese      | CheeseFries    |
|   Chicken     | Zinger         |
|   Carbonated  | Pepsi          | 
|   Beef        | Whopper        |
+---------------+----------------+

如上所示,每个餐厅都可以有多个分店,每个分店可以有多个类别,每个类别可以有多个子类别,然后每个子类别中可以有多个项目。分店可能具有相同的类别和/或子类别,但其中的项目不同。
在这种情况下,我认为集中式的类别、子类别和项目表不适用,因为每个餐厅的每个分店都是其自己独立的实体,需要其自己的一组类别、子类别和项目表。如果是这样,我该如何创建表,并设置必要的外键呢?
Categories
+----------------+
|  Categories    |
+----------------+
|  Drinks        |
|  Burgers       | 
|  Fries         | 
|  SetMeals      |  
+----------------+

SubCategories
+----------------+----------------+
| Category       |  SubCategories |
+---------------+-----------------+
| Drinks         | Carbonated     |
| Drinks         | Carbonated     |
| Drinks         | Carbonated     |
| Drinks         | Non-Carbonated |
| Burgers        | Beef           |
| Burgers        | Beef           |
| Burgers        | Chicken        |
+----------------+----------------+

SubCategories
+----------------+----------------+-------------+
| Category       |  SubCategories | Items       |
+---------------+-----------------+-------------+
| Drinks         | Carbonated     | Pepsi        |
| Drinks         | Carbonated     | Root Beer    |
| Drinks         | Carbonated     | Cola         |
| Drinks         | Non-Carbonated | Orange Juice |
| Burgers        | Beef           | Whopper      |
| Burgers        | Beef           | Cheese Burger|
| Burgers        | Chicken        | McChicken    |
+----------------+----------------+--------------+

当然,我的想法也可能是错误的,对于这种情况而言,中心化表格可能会更为适用。如果是这样,请提供一些示例或指导,以便设置这些表格。

我考虑了以下解决方案:

Restaurants
+-------------+----------------+
| RestaurantID| RestaurantName | 
+-------------+----------------+
|     1       | PizzaHut       |
|     2       | BurgerKing     |
|     3       | KFC            | 
|     4       | SubWay         |
+-------------+----------------+

Branches
+---------------+----------------+
| RestaurantName| BranchAddress  | 
+---------------+----------------+
|  KFC          | XXX-1234       |
|  KFC          | AAA-1234       |
|  KFC          | YYY-1234       | 
|  BurgerKing   | DDD-1234       |
+-------------+------------------+

Categories
+----------------+----------------+----------------+
| RestaurantName | BranchAddress  | Category       | 
+----------------+-----------------+----------------+
|  KFC           |     XXX-1234   | Fries          |
|  KFC           |     AAA-1234   | Burgers        |
|  KFC           |     YYY-1234   | Drinks         | 
|  BurgerKing    |     DDD-1234   | Burgers        |
+----------------+----------------------------------+

SubCategories
+----------------+----------------+----------------+----------------+
| RestaurantName | BranchAddress  | Category       |  SubCategories |
+----------------+-----------------+---------------+----------------+
|  KFC           |     XXX-1234   | Fries          | Cheese         |
|  KFC           |     AAA-1234   | Burgers        | Chicken        |
|  KFC           |     YYY-1234   | Drinks         | Carbonated     |
|  BurgerKing    |     DDD-1234   | Burgers        | Beef           |
+----------------+---------------------------------+----------------+

Items
+----------------+----------------+----------------+----------------+-------------+
| RestaurantName | BranchAddress  | Category       |  SubCategories | Items       |
+----------------+-----------------+---------------+----------------+-------------+
|  KFC           |     XXX-1234   | Fries          | Cheese         |CheeseFries  |
|  KFC           |     AAA-1234   | Burgers        | Chicken        |Zinger       |
|  KFC           |     YYY-1234   | Drinks         | Carbonated     |Pepsi        |
|  BurgerKing    |     DDD-1234   | Burgers        | Beef           |Whopper      |
+----------------+---------------------------------+----------------+-------------+

尽管上述表格为每个餐厅及其分店提供了各自的类别、子类别和项目,但这违背了最初拆分它们的整体目的,而且相当愚蠢。编辑:我试图对上述表格进行反规范化,以便可以使用查询来查询它。
$query="SELECT * FROM Items WHERE Restaurantname='BurgerKing' AND 
BranchAddress='XXX-1234' AND Category='Fries';
$result=mysqli_query($cxn,$query) or die("Error");
while($row=mysqli_fetch_assoc)
{
extract($row);
echo "$Item";
}

注意:我计划将数据库扩展到包括非快餐餐厅甚至非餐饮相关的商店,因此各种表格(类别/子类别和项目)必须能够包括来自非餐饮相关商店的类别(例如电子产品/书籍等)。
非常抱歉问题很长,希望能得到任何建议和帮助。
谢谢!

你为什么这样去反规范化它?你为什么要按分支地址有子类别?谁知道,也许这是合法的。你说的“它毁掉了整个目的,而且很愚蠢”是什么意思? - Drew
@ Drew Pierce我编辑了我的问题,以展示为什么我将它非规范化为这样。我只是觉得这很愚蠢,因为与其像这样非规范化,我不如将所有东西都合并到一个巨大的表格中,然后像使用Excel表格一样使用它,使用诸如过滤器之类的查询。例如(SELECT * FROM Item WHERE RestaurantName='KFC';)而无需在查询中使用JOINS,尽管这样做会背离关系数据库的整个目的。@ yvytty - Kenneth .J
1个回答

0

我不确定为什么你要进行去规范化。你可以从categories和subcategories中取出与分支相关的列,从subcategories中取出类别名称等。如果你将它们留在其中,你就会复制大量的数据,而这并不是传统关系型数据库的工作方式!你还应该通过ID来关联这些表,而不是通过名称,因为连接时比较速度更快。

你可以考虑使用多对多链接表来将项目与分支链接起来。这样,你就可以满足需求,将特定类别/子类别的特定项目与分支相关联,而无需将整个类别/子类别相关联。

CREATE TABLE item_link (
  id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  branch_id INT(11) NOT NULL,
  item_id INT(11) NOT NULL,
  KEY composite (`branch_id`, `item_id`)
);

看看我为你做的fiddle,详细说明了我对你的模式所提出的更改,并且给出了一个使用这个新表格来显示分店菜单/库存的示例。


我对表进行了反规范化处理,这样我就可以在不使用任何联接的情况下使用查询。你的示例中关键字KEY是什么作用?我尝试搜索了一下,但只得到了复合主键的结果,但在使用KEY关键字之前已经设置了主键,这并没有意义。(我指的是item_link表以及其他表,例如(chains)) - Kenneth .J
反规范化应该只在极少数情况下使用,通常是当表格非常庞大(数十亿条记录)且索引无法满足性能要求时。请参阅Jeff Atwood的这篇文章以获取更多信息。关键字key添加了一个索引。如果您查看fiddle中查询的执行计划,您将看到复合键用于检索与item_link连接的记录。 - Erin Schoonover

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接