何时使用映射表

时间:2013-01-19 15:38:48

标签: php mysql

在MySQL中,如果我有一定数量的categories永远不会改变,我应该在他们分类的东西的表中创建bool字段,还是应该使用映射表?如果是这样,为什么?


案例A:

t_stuff

id (int) 
name (string) 
category_a (bool) 
category_b (bool) 
category_c (bool) 
category_d (bool) 
category_e (bool) 
category_f (bool)

案例B:

t_stuff

id (int)
name (string)

t_categories

id (int)
name (string)

t_stuff_category

id (int)
stuff_id (int)
category_id (int)

虽然A看起来并不像B那样“好看”,但就所需的查询而言似乎更简单了吗?

编辑:我觉得我应该补充说我需要做的就是:

  • 获取所有内容行
  • 获取所有具有特定类别
  • 的行
  • 获取一个具有特定ID的东西行

2 个答案:

答案 0 :(得分:3)

绝不使用案例A。它违反了关系数据库的原则。了解normalization

假设您要查找id的{​​{1}},则需要检查category = 1中的每一列:

A

这种设计不仅难以查询,而且也是聚合的噩梦。如果您想获得特定SELECT id FROM t_stuff WHERE category_a = 1 OR category_b = 1 OR category_c = 1 OR category_d = 1 OR category_e = 1 OR category_f = 1 的{​​{1}}类别,该怎么办?

如果是COUNT(*),您只需查询一个属性:

id

要获取B,您只需替换SELECT stuff_id FROM stuffCategory WHERE category_id = 1

此外,COUNT(*)下您不需要id。 (id)的复合主键就足够了。

答案 1 :(得分:1)

这里最重要的是“永不言败” - 在问题和评论中,你自信地说:

  • 类别的数量(以及隐含的含义)从不更改
  • 从不需要查询“项目X中有多少类别”等内容

随着时间的推移,需求会发生变化,并且基于预测某些事情从不发生而设计系统可能会在以后导致挫败感,因为您必须解决设计中的限制。

当然,去标准化版本有一些优点(只有布尔列),但实际上只有你有一个非常少的“类别”(我会说< = 3),这样你才可以将它们视为“属性”而不是“类别”:

  1. 搜索A类或B类中的所有产品稍微容易一些,因为如果同时使用该产品,则无需担心JOIN子句的影响。
  2. 有些查询更容易编写,因为您无需担心JOIN子句。
  3. 您可以使用标准化设计而不是一组布尔列来执行以下操作:

    1. 只需使用SQL COUNT()
    2. 计算产品的类别数
    3. 在数据库中存储有关类别本身的信息,而不必将其隐藏在应用程序代码中的某个位置。除了选项B架构中建议的名称列之外,您可能还需要更长的描述,或者应该显示该类别的标志等。
    4. 添加,删除或重命名类别,而无需触及应用程序代码的任何一行。
    5. 同样,您可能不想做任何现在这些事情,但除非您计划在一周内丢弃该应用程序,您无法预测未来的要求。软件设计的很大一部分是使代码可维护,并在简单性和灵活性之间进行合理的折衷。