Php 何时使用映射表

Php 何时使用映射表,php,mysql,Php,Mysql,在MySQL中,如果我的类别数量有限,而且永远不会改变,那么我应该在它们所分类的表中创建它们作为bool字段,还是使用映射表?若然,原因为何 案例A: t_的东西 id (int) name (string) category_a (bool) category_b (bool) category_c (bool) category_d (bool) category_e (bool) category_f (bool) id (int) name (string) 案例B:

在MySQL中,如果我的类别数量有限,而且永远不会改变,那么我应该在它们所分类的表中创建它们作为bool字段,还是使用映射表?若然,原因为何

案例A:

t_的东西

id (int) 
name (string) 
category_a (bool) 
category_b (bool) 
category_c (bool) 
category_d (bool) 
category_e (bool) 
category_f (bool)
id (int)
name (string)
案例B:

t_的东西

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

id (int)
name (string)
t_材料_类别

id (int)
stuff_id (int)
category_id (int)
虽然A看起来不如B好,但就所需的查询而言,它看起来确实简单得多

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

把所有的东西都排好 获取具有一个特定类别的所有资料行 获取一个具有特定id的填充行 不要使用用例A。它违反了关系数据库的原则。了解

假设您要查找category=1的id,则需要在以下情况下检查每一列:

这种设计不仅使查询变得困难,而且对于聚合来说也是一场噩梦。如果您想获得特定id的类别计数*,该怎么办

在案例B中,您只需查询单个属性:

SELECT stuff_id 
FROM   stuffCategory
WHERE  category_id = 1 
要获得计数*,只需替换id

此外,您不需要t_stuff_类别下的id。stuff\u id、category\u id的复合主键就足够了。

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

假设您要查找category=1的id,则需要在以下情况下检查每一列:

这种设计不仅使查询变得困难,而且对于聚合来说也是一场噩梦。如果您想获得特定id的类别计数*,该怎么办

在案例B中,您只需查询单个属性:

SELECT stuff_id 
FROM   stuffCategory
WHERE  category_id = 1 
要获得计数*,只需替换id


此外,您不需要t_stuff_类别下的id。stuff\u id、category\u id的复合主键就足够了。

这里最重要的事情是永不说永不——在问题和评论中,您自信地声明:

类别的数量和含义永远不会改变 您将永远不需要查询诸如项目X包含多少类别之类的内容 随着时间的推移,需求会发生变化,并且基于某些事情永远不会发生的预测来设计系统可能会导致以后的挫折,因为您必须克服设计中的限制


诚然,仅使用布尔列的非规范化版本有一些优点,但实际上只有在类别非常少的情况下,我想说这里最重要的是永不说永不-在问题和评论中,您自信地声明:

类别的数量和含义永远不会改变 您将永远不需要查询诸如项目X包含多少类别之类的内容 随着时间的推移,需求会发生变化,并且基于某些事情永远不会发生的预测来设计系统可能会导致以后的挫折,因为您必须克服设计中的限制


诚然,只使用布尔列的非规范化版本有一些优点,但实际上只有在类别非常少的情况下,我会说您的case B查询似乎与设计不匹配。另外,我永远也不想找到您提到的案例A。我要么要所有行,要么要所有具有一个特定类别的行。@Ben希望这会有所帮助。关于使用复合主键,请确保在创建表时创建唯一的索引/约束。如果您意外地得到了重复的行,并且没有自动递增键,那么删除重复行可能会非常麻烦。但是事先需要获取stuff_id,之后仍然需要基于category_id获取类别信息。在案例B中进行3次查询,在案例A中进行1次查询。是否进行查询?@Ben如果您需要结果中多个表的信息,只需使用SQL JOIN子句;不需要多个查询。您的案例B查询似乎与设计不匹配。另外,我永远也不想找到您提到的案例A。我要么要所有行,要么要所有具有一个特定类别的行。@Ben希望这会有所帮助。关于使用复合主键,请确保在创建表时创建唯一的索引/约束。如果您意外地得到了重复的行,并且没有自动递增键,那么删除重复行可能会非常麻烦。但是事先需要获取stuff_id,之后仍然需要基于category_id获取类别信息。在案例B中进行3次查询,在案例A中进行1次查询。是否进行查询?@Ben如果您需要结果中多个表的信息,只需使用SQL JOIN子句;不需要多个查询。是的,没错,我从来不需要做你在两个要点中提到的事情。这就是提出优化问题的全部意义所在。如果这可能会发生变化,我显然不得不选择案例B。我不知道
我相信你会同意有些东西是不变的,比如rgb颜色系统中的r、g和b。这些可能是我的分类,仅举一个例子,不是最好的。不过,我认为你是对的,将它们命名为属性而不是类别可能会更容易理解。这是到目前为止唯一一个回答,它实际上解决了我的问题,所以+1。@Ben我个人不认为“r”、“g”和“b”是类别;它们是单个数据的固有属性,它们也不是布尔值,但我确实理解你的观点,并且在我的回答中提到了属性。你的问题的措辞方式是,在你匿名的例子中,你有一个6个命名类别的列表,其中可能包含你的项目;这与具有某些固有属性的项目不同。@Ben要在刻度两端给出一些极端值,删除的属性显然不是要放入映射表中的类别;然而,这些类别是防水的,是循环的,显然来自于一个无限的类别列表,这些类别可以很容易地扩展到包含食用等,即使最初的要求给出了一个明确的列表。很明显,根据你的分类列表从根本上的固定程度,你可以决定在你的案例中什么是有意义的。是的,没错,我从来不需要做你在两个要点中提到的事情。这就是提出优化问题的全部意义所在。如果这可能会发生变化,我显然必须选择案例B。我不需要做1、2或3,即使2显然很好。我相信你会同意,有些东西是不变的,比如rgb颜色系统中的r、g和B。这些可能是我的分类,仅举一个例子,不是最好的。不过,我认为你是对的,将它们命名为属性而不是类别可能会更容易理解。这是到目前为止唯一一个回答,它实际上解决了我的问题,所以+1。@Ben我个人不认为“r”、“g”和“b”是类别;它们是单个数据的固有属性,它们也不是布尔值,但我确实理解你的观点,并且在我的回答中提到了属性。你的问题的措辞方式是,在你匿名的例子中,你有一个6个命名类别的列表,其中可能包含你的项目;这与具有某些固有属性的项目不同。@Ben要在刻度两端给出一些极端值,删除的属性显然不是要放入映射表中的类别;然而,这些类别是防水的,是循环的,显然来自于一个无限的类别列表,这些类别可以很容易地扩展到包含食用等,即使最初的要求给出了一个明确的列表。很明显,根据你的分类列表从根本上的固定程度,你可以决定在你的案例中什么是有意义的。