处理多对多的关系

时间:2013-11-25 20:42:55

标签: mysql sql

这是我正在制作的表格:
restaurant(餐厅信息)
restaurant_hours(餐厅营业时间)
restaurant_tags(关于餐馆的标签)

1个餐厅可以有超过1个restaurant_hours和超过1个restaurant_tags

查询多个表的结果:

+----+---------------+-------+---------+---------+-----------+------------+-------+
| id | name          | state | cuisine | day     | open_time | close_time | tag   |
+----+---------------+-------+---------+---------+-----------+------------+-------+
| 44 | Restaurant A  | png   | local   | mon-sun |   08:00   | 19:00      | none  |
| 45 | Restaurant B  | kdh   | western | mon-sun |   00:00   | 19:00      | none  |
| 46 | Restaurant C  | png   | western | mon-fri |   09:00   | 19:00      | none  |
| 46 | Restaurant C  | png   | western | sat-sun |   10:00   | 23:00      | wifi  |
| 46 | Restaurant C  | png   | western | sat-sun |   10:00   | 23:00      | coke  |
| 46 | Restaurant C  | png   | western | sat-sun |   10:00   | 23:00      | cofee |
+----+---------------+-------+---------+---------+-----------+------------+-------+

正如您所见,由于多个小时的操作(46dayopen_time)值或标记值,ID为close_time的餐馆会有多行。

这个数据非常繁琐,我不能假设每一行属于不同的餐厅

如何让应用程序代码更容易处理这些数据?

我能想到的一种方法是将餐厅合并成一排(这是正确的方法吗?还有其他办法吗?)

使用subquerygroup_concat,我最终得到类似的内容:

+---------------+---------------------+-------+---------+-------------------------------------+-------------------------+----------------------------+-------------------------+
| restaurant_id | name                | state | cuisine | day                                 | open_time               | close_time                 | tag                     |
+---------------+---------------------+-------+---------+-------------------------------------+-------------------------+----------------------------+-------------------------+
|            44 | Restaurant A        | png   | local   | mon-sun                             | 08:00                   | 19:00                      | none                    |
|            45 | Restaurant B        | kdh   | western | mon-sun                             | 00:00                   | 19:00                      | none                    |
|            46 | Restaurant C        | png   | western | mon-fri , sat-sun, sat-sun, sat-sun | 09:00,10:00,10:00,10:00 | 19:00, 23:00, 23:00, 23:00 | none, wifi, coke, cofee |
+---------------+---------------------+-------+---------+-------------------------------------+-------------------------+----------------------------+-------------------------+

一般来说,这就是我一直在做的事情 对于可能具有多于1个值的任何列,应用程序代码只需要用逗号分隔

问题:
1)这是正确的方法吗?
2)列长度是否有限,因为group_concat可能产生非常宽的列

我很想知道其他程序员如何处理这类问题

被修改
使用php作为应用程序代码

2 个答案:

答案 0 :(得分:1)

多值字段总是很难处理。虽然第一种方法产生更多列,但它也更简洁,更容易查询。

简短回答:如果您重视空间,请选择选项2.如果您重视可用性,请选择选项1.

答案 1 :(得分:0)

Group_concat可能不是您的最佳选择,因为存在大小限制(并且它不是硬限制,它基于一些其他设置)。引用mysql 5.0 docs

  

结果被截断为由。给出的最大长度   group_concat_max_len系统变量,其默认值为   1024.该值可以设置得更高,尽管返回值的有效最大长度受值的约束   max_allowed_pa​​cket的。

只是不要尝试“一刀切”查询您所做的一切。我不会每次加入所有表格(如果你不需要),只在需要时才这样做。如果您需要在大多数情况下查询此信息,可能更容易在您的应用程序端使用“后期处理”功能将其转换为更简单的形式 - 例如,多维数组。现在,事实上你有2个1-many关系正在进行,这就加剧了问题。简单地运行嵌套查询可能更容易,具体取决于我们谈论的数据量 - IE,获取所有餐馆数据,然后为每个餐馆获取时间,然后获取标签。如果这会导致数百个查询,您可以通过查询餐厅表,然后查询小时和标签表的每一行,在程序代码中执行“加入”来消除所有这些问题。这里的诀窍是以一种可以在整个应用程序中使用的方式来实现,而不会减慢速度或使用太多内存。如果我们谈论的餐馆数量不到几百家,并且我们在那里有非常大的文本列中没有blob列,那么你应该把它们加载到php并处理它们,这应该是很好的记忆...否则,你可能只需要你去的时候处理这​​个,因为你发现它很难看。

绝对最好的情况是,您不必在大多数时间将所有这些数据汇集在一起​​。