1

在 MySQL 中,如果我有一个永远不会改变的有限数量,categories我应该将它们创建为它们分类的表中的布尔字段,还是应该使用映射表?如果是这样,为什么?


案例一:

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 的东西行
4

2 回答 2

3

从不使用 case A。它违反了关系数据库的原则。了解规范化

假设您要查找idfor 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

这种设计不仅使查询变得困难,而且也是聚合的噩梦。如果您想获取COUNT(*)特定类别的类别id怎么办?

万一B,您只需查询一个属性:

SELECT stuff_id 
FROM   stuffCategory
WHERE  category_id = 1 

要获得COUNT(*),您只需更换id.

此外,您不需要idt_stuff_category. ( ) 的复合主键stuff_id, category_id就足够了。

于 2013-01-19T15:42:06.737 回答
1

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

  • 类别的数量(以及隐含的含义)永远不会改变
  • 永远不需要查询诸如“项目 X 有多少类别”之类的问题

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

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

  1. 搜索 A 类或 B 类中的所有产品稍微容易一些,因为如果产品同时在这两种情况下,您不必担心JOIN子句的影响。
  2. 有些查询编写起来更简单一些,因为您不需要担心JOIN子句。

您可以使用规范化设计而不是一组布尔列来执行以下操作:

  1. 只需使用 SQL 计算产品的类别数COUNT()
  2. 将有关类别本身的信息存储在数据库中,而不必将其隐藏在应用程序代码中的某个位置。除了选项 B 架构中建议的名称列外,您可能还需要更长的描述,或何时显示该类别的标志等
  3. 添加、删除或重命名类别,而无需触及应用程序代码的任何一行。

同样,您现在可能不想做任何这些事情,但除非您计划在一周内丢弃该应用程序,否则您无法预测未来的需求。软件设计的很大一部分是关于使代码可维护并在简单性和灵活性之间进行合理折衷。

于 2013-01-19T16:17:22.857 回答