在MySQL中,n*n表与(n^2)*3表的区别是什么?

3

前一段时间我发布了一个关于列顺序的不同问题。虽然这个问题与列顺序无关,但建议我按照不同的方式制作表格。

假设我正在销售100种产品。其中一些产品是相互兼容的,而有些则不是。有些产品尚未经过测试(我在上一个问题中没有提到这一点)。

我是否最好制作一个类似于mySQL表格的表格:

NAME         PRODUCT1     PRODUCT2     PRODUCT3     PRODUCT4 ....
product1     yes          no           maybe        yes
product2     maybe        yes          no           no
product3     maybe        yes          no           no
product4     maybe        yes          no           no
...

或者将表格制作成这样:
FIRST       SECOND      COMPATIBLE?
Product1    Product1    Yes
Product1    Product2    Yes
Product1    Product3    No
Product1    Product4    Maybe
Product2    Product1    Maybe
Product2    Product2    Maybe
Product2    Product3    No
Product2    Product4    Maybe
Product3    Product1    Yes
Product3    Product2    Yes
Product3    Product3    No
Product3    Product4    Yes
Product4    Product1    Yes
Product4    Product2    No
Product4    Product3    No
Product4    Product4    Maybe

我被告知第二种方法更好,但我没有提到还有“可能”的选项(不仅仅是是/否),这意味着第二个表格需要添加第三列。
作为一个经验不足的mySQL用户,我想问,哪个表格更有效率、更易于维护,你会推荐哪个呢?
3个回答

3
第二个选项仍然更好(即使有第三列,这也不是问题),因为它允许您轻松添加新的产品类型而无需修改表格。(技术术语是模式更好“规范化”)。这样更易于维护。此外,这意味着您可以更轻松地跨越该表进行连接,或者进行查询以回答“哪种与产品1兼容的最低成本产品”,这在第一个表中非常难以实现。

希望您不介意再问一个问题。我已经布置好了第二个表格,但还没有填充。我的意思是:每个产品都与自身兼容,因此我已经为每个与自身兼容的产品填写了信息。但是我还没有混合产品的兼容性信息。有没有一种快速填充SECOND中每个非唯一FIRST的方法?希望您能理解我的拙劣措辞。 - thomas
@thomas:最好的方法可能是编写代码,在读取现有产品列表时执行插入操作...从某个地方读取? - FrustratedWithFormsDesigner
@thomas,很高兴我能帮到你...请将你的第二个问题作为另一个问题发布在StackOverflow上,而不是在评论中 :) 一旦你发布了链接,你可以在这里发布! - nicolaskruchten
你可以考虑使用浮点值来表示“兼容性”,范围在1.0到0.0之间。这样,如果需要以1990年代模糊逻辑的方式处理更多的“可能性”,你就能够处理更多的渐变。除此之外,这是正确的方法。我们在我的工作室里经常做这种事情,它表现良好,而且维护起来也不难。 - O. Jones

2

建议选择第二个选项。如果您添加或删除产品,只会影响一些行。如果使用第一个选项并添加/删除产品,则会更改表的结构。


-1

还有第三个选项 - “半规范化”形式。在这种情况下,您将拥有类似于以下结构的结构:

Product  DefinitelyCompatible  MaybeCompatible
----------------------------------------------
 1        '2, 3, 4'             '5'
 2        '1, 4'                '3'
 3        '1'                   '3, 4'
 4        '1, 2'                '3'
 5        ''                    '1'

第一个字段是产品ID,第二个和第三个字段是包含ID列表的字符串。使用这种结构,您可以使用{{link1:FIND_IN_SET()}} MySQL函数搜索列表,或者如果您想查找给定产品的兼容性,则只需要获取一行,然后自己拆分字符串。

这样,您只需要拥有与产品数量相同的行(在Nx3表中),同时最小化您需要更改以添加新产品(或更新现有产品)的行数。

关于性能的进一步说明 - 假设关系是对称的(如果 a -compat-> b,则 b -compat-> a),您甚至不需要使用 FIND_IN_SET() - 您只需获取您需要获取列表的任何对象(a 或 b)(如果您需要获取与 23 兼容的所有内容,则获取 23 的行;如果您想查看 4 是否与 5 兼容,则可以获取任意一个的行并查看另一个是否出现在其中)。FIND_IN_SET() 只有在检查是子查询的一部分而不是在代码中时才是必要的。

1
这绝非实现此关联的最佳方法,特别是在像这样的产品数据库中。也许在数据仓库方案中,这个解决方案会起作用,但下面njk指出了这个设计的众多问题之一。 - Isabelle Wedin
1
现在我想起来了,可能永远不需要索引“DefinitelyCompatible”和“MaybeCompatible”。但联接查询可能会有些棘手。 - FrustratedWithFormsDesigner
那是真的,我没有考虑查询。 - thomas
2
将分隔数据存储在数据库中几乎总是一个坏主意,特别是对于像这样简单的东西。有什么优势吗?更少的行数? - nicolaskruchten
有时候,仅仅获取所有的数据项可能比每次请求DB引擎进行联接更加高效。如果你在使用的数据模型中几乎总是只需要查询“与X相关的东西是什么”,而不涉及归一化帮助处理的更复杂的查询,那么分隔数据将会更加高效。当然,当你手中只有一个数据库引擎锤子时,所有东西看起来都像是连接钉子,但这并不总是正确的。 - Amber
显示剩余2条评论

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