【问题标题】:What is the best approach in SQL to store multi-level descriptions?SQL 中存储多级描述的最佳方法是什么?
【发布时间】:2010-12-28 13:17:04
【问题描述】:

我需要一个新的视角来了解如何设计一个可靠且高效的 SQL 数据库来存储多级数据数组。

这个问题适用于很多情况,但我想出了这个例子:
有数百种产品。每个产品都有未定义数量的零件。每个部分都由几个元素组成。

所有产品都以相同的方式描述。所有零件都需要相同的字段来描述它们(例如:价格、重量、零件名称),所有零件的所有元素也具有统一的设计(例如:元素代码、制造商)。简单明了。
一个元素可能只与一个部分相关,而每个部分只与一个产品相关。

我想出了三个表的想法:

Products:
--------------------------------------------
prod_id   prod_name   prod_price   prod_desc 
1            hoover          120      unused

下一个

Parts:
----------------------------------------------------
part_id  part_name  part_price  part_weight  prod_id
      3     engine          10           20        1

最后

Elements:
---------------------------------------
el_id  el_code  el_manufacturer part_id
    1    BFG12               GE       3

现在,选择所需的产品,从 PARTS 中选择所有 prod_id 相同的产品,然后从 ELEMENTS 中选择所有 part_id 匹配的产品 - 经过多次查询后,您已获得所有数据。

我只是不确定这是否是正确的方法。
我还有另一个想法,没有 ELEMENTS 表。
这会减少查询,但我有点担心这可能是蹩脚和不好的做法。
代替 ELEMENTS 表,PARTS 表中还有两个字段,所以它看起来像这样:
part_id、part_name、part_price、part_weight、prod_id、part_el_code、part_el_manufacturer
它们将是 text 类型,并且对于每个部分,有关元素的信息将存储为字符串,这样:

part_el_code         | code_of_element1; code_of_element2; code_of_element3

part_el_manufacturer | manuf_of_element1; manuf_of_element2; manuf_of_element3

然后我们只需要从这些字段中分解()数据,然后我们得到数组,易于显示。 当然这并不完美,也有一定的局限性,但是这个想法可以吗?

我想出第二个变体的原因是第三个表格——元素——最终会变得相当大。如果有 10,000 个产品,每个产品有 4 个零件,平均每个零件有 3 个元素 - 这意味着元素表中必须有 120,000 行。老实说 - 我真的不知道这是否会导致性能问题。

我应该只采用第一个想法吗?或者也许有更好的方法来解决这个问题?

【问题讨论】:

  • 查找 BOM“材料清单”

标签: sql arrays multidimensional-array


【解决方案1】:

描述事物之间的关系正是关系数据库所做的。任何关于 SQL 的书都应该给出很多例子,我建议寻找这样的书来更好地理解这些问题,但我会快速回答你的问题。

对于使用 3 个表的简单解决方案,您正走在正确的轨道上,但您不需要三个 select 语句。这就是join 的用途。在您的示例中,以下 select 语句将为您提供特定产品的所有数据。

select * 
from product
join parts on parts.prod_id = product.prod_id
join elements on elements.part_id = part.parts_id
where product.prod_id = x

这很好,可以完全满足您的要求。


就你的第二个想法而言,这真的很糟糕。您正在使用关系数据库,它允许您存储数据集并将其关联。将列表存储在字符串值中就是忽略了关系数据库旨在做好的确切功能。


但是,有一种方法可以改进您的设计。我认为您可能并不总是对产品和零件或零件和元素保持一对一的关系。所以我建议以下。

首先从部件表中删除 prod_id,然后从元素表中删除 part_id。

然后创建两个“连接表”。让我们称它们为 prodparts 和 partselement。它们看起来像这样:

prodparts would contain two columns prod_id and part_id (and maybe a count?)
partselement would contain two columns part_id and el_id (and maybe a count?)

现在这些表中的每一行都将描述这种关系。但是,这是整洁的部分,多个产品可以使用相同的部分,并且多个部分可以使用相同的元素。

选择只是稍微复杂一些,看起来像这样:

select * 
from product
join prodparts on procparts.prod_id = product.prod_id
join parts on parts.part_id = prodparts.part_id
join partselement on partelement.part_id = parts.part_id
join elements on elements.el_id = partelement.parts_id
where product.prod_id = x

【讨论】:

  • 感谢所有 cmets 和想法。我会考虑您提出的改进建议。
  • 另外 - 我担心性能 - Elements 表可能会变得非常大,可能超过 100,000 行。
  • @gime : sql 服务器旨在处理大型数据集并很好地链接——你可以做一些事情来帮助——设置索引可能是最重要的。如果您的所有表都有良好的索引(并且服务器没有资源匮乏),那么 100k 应该不是问题。
【解决方案2】:

您的第一种方法似乎很可靠。第二种方法将难以维护元素的数据。我在第一个设计中注意到的一件事是产品和零件都有一个“价格”。它们是否意味着不同的东西,或者零件价格的总和是否等于产品的最终价格?如果是这样,我建议在产品级别删除价格字段并在零件级别使用 sum() 函数。

除此之外……干得好!

【讨论】:

  • 感谢您的及时回复。
猜你喜欢
  • 2020-04-28
  • 2019-10-21
  • 1970-01-01
  • 2011-02-19
  • 2013-05-23
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多