MySQL,如何从另一个表中将多个值存储在单个列中?

13


请谅解,我不太擅长解释事情,甚至不知道这个问题的适当标题
好的,大家我有这个问题:
我已经有一个名为meal的表了

+------+--------+-----------+---------+
|  id  |  name  | serving   |  price  |
+------+--------+-----------+---------+
|  1   | soup1  |  2 person |  12.50  |
+------+--------+-----------+---------+
|  2   | soup2  |  2 person |  15.50  |
+------+--------+-----------+---------+
|  3   | soup3  |  2 person |  23.00  |
+------+--------+-----------+---------+
|  4   | drink1 |  2 person |  4.50   |
+------+--------+-----------+---------+
|  5   | drink2 |  2 person |  3.50   |
+------+--------+-----------+---------+
|  6   | drink3 |  2 person |  5.50   |
+------+--------+-----------+---------+
|  7   | frui1  |  2 person |  3.00   |
+------+--------+-----------+---------+
|  8   | fruit2 |  2 person |  3.50   |
+------+--------+-----------+---------+
|  9   | fruit3 |  2 person |  4.50   |
+------+--------+-----------+---------+

现在我想允许管理员从这个meal表创建一个套餐餐。这意味着,一个套餐可以有无限数量的菜品。

目前我困惑于如何将套餐与菜品存储/链接起来,我不想存储以下内容:

+------+--------------+-----------+-----------+
|  id  |  combo_name  | serving   |  meal_id  |
+------+--------------+-----------+-----------+
|  1   |   combo1     |  2 person |   1,4,7,9 |
+------+--------------+-----------+-----------+
|  2   |   combo2     |  2 person |   2,5,8   |
+------+--------------+-----------+-----------+
|  4   |   combo3     |  2 person |   3,5,6,9 |
+------+--------------+-----------+-----------+

看看meal_id这一列,我认为这不是一个好的数据存储方式。

3个回答

24
创建一个多对多的关联表:
combo_id    meal_id
1           1
1           4
1           7
1           9
2           2
2           5
2           8
3           3
3           5
3           6
3           9
选择给定套餐中的所有餐点:
SELECT  m.*
FROM    combo_meal cm
JOIN    meal m
ON      m.id = cm.meal_id
WHERE   cm.combo_id = 1

在检索数据时,与询问者的结构相比,这是否需要更多的循环来处理,因为可以处理该字符串以获取多个值。我也感到困惑! - Ayush Goyal
@AyushGoyal:具体是检索哪些数据? - Quassnoi
嗨,如果有包含近300个值的全选选项,使用这种方法是否好?还是我应该使用一个标志来识别它是全部选择。 - Himanshu Bhandari
@himanshu:请将其发布为一个问题,包括您的数据布局和一个样本查询。 - Quassnoi
@Quassnoi:没错,这是我的问题,请给出您的意见。http://dba.stackexchange.com/questions/165396/approach-to-save-many-to-many-relationship-in-case-select-all-values - Himanshu Bhandari
这真的是正确的方法吗?我一直认为自己在整个过程中都做错了。 - Muhammad Ibnuh

5
不,把数据存储在这种方式绝对不是一个好的选择。使用一个“combo_header”表和一个“combo_details”表会更好。
“combo_header”表类似于:
```html combo_header ```

而“combo_details”表则类似于:

+------+--------------+-----------+
|  id  |  combo_name  | serving   |
+------+--------------+-----------+
|  1   |   combo1     |  2 person |
+------+--------------+-----------+
|  2   |   combo2     |  2 person |
+------+--------------+-----------+
|  4   |   combo3     |  2 person |
+------+--------------+-----------+

然后,combo_details 将会是这样的:
+------+-----------+
|  id  |  meal_id  |
+------+-----------+
|  1   |  1        |
+------+-----------+
|  1   |  4        |
+------+-----------+
|  1   |  7        |
+------+-----------+
|  1   |  9        |
+------+-----------+
... / you get the idea!

顺便提一下,如果在单个列中使用多个值,您将违反关系数据库的第一范式。

我提出的方法将使您可以轻松回答查询,例如“获取combo1所有餐点的名称”。


1

这被称为餐点和套餐之间的多对多关系。一种餐点可以列在多个套餐中,而一个套餐也可以包含多种餐点。您需要一个链接表(而不是combo.meal_id字段),其中包含所有可能的餐点-套餐对。

最终,您将拥有三个表:

  1. 餐点(meal_id,serving,name)
  2. 套餐(combo_id,serving,name)
  3. 餐点_套餐(autoid,meal_id,combo_id)

meal_combo.autoid并不是必需的,这只是一般建议。

要列出包含所有餐点的套餐:

SELECT meal.id, meal.name FROM comboINNER JOIN meal_combo ON meal_combo.combo_id = combo.id INNER JOIN meal ON meal.id = meal_combo.meal_id WHERE combo.id = 132

搜索“多对多关系”或“数据库链接表”以获取详细信息。


当我还是个男孩时,第一次使用无限的力量智慧时,我个人感到了无穷的力量和智慧。 - Dercsár

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