避免存储所有可能产品配置的排列

时间:2018-08-21 00:16:44

标签: sql database-design

我将使用衬衫类比简化我的问题。我有以下表格:

  • 衬衫尺寸(例如小,中,大...)
  • 衬衫颜色(例如红色,绿色,蓝色...)
  • 衬衫样式(例如,短袖,长袖,领...)

现在,我想为库存创建价格。并非所有衬衫在每种配置中都可用,但有些衬衫可用。例如:

  • 所有衬衫样式和尺寸均以绿色显示。这些是$ 1。
  • 只有蓝色的大领衬衫。这些是2美元。
  • 各种尺寸的短袖红色衬衫$ 3,长袖和领红色衬衫$ 4。

我可以创建具有三个表的所有可用组合的另一个表并存储价格。这似乎效率低下并且容易出错。我还能如何存储这些关系?

2 个答案:

答案 0 :(得分:2)

背景

在研究如何完成某件事时,了解术语和词典很重要。您在这里要做的基本上是设计一个产品配置器配置价格报价(CPQ)系统。这些系统作为可定制的专有和开源资源存在。作为一家中端B2B公司的软件架构师,我非常熟悉从头实现cpq的软件以及与COT解决方案集成的软件。如果这只是学术研究,我强烈建议您看一下免费的OSS CPQ工具。但是,由于这是堆栈溢出,因此我将在更多技术层面上解决您的问题。

四个抽象层

设计产品配置系统(我们将其称为产品配置模型)实质上有四个抽象层。

  • 组件和子组件
  • 这些组件之间共享的属性
  • 连接组件和子组件及其共享属性的表/关系约束
  • 表达式和表达式约束(在概念上是底层的不可重用语句)

组件

在这里,我们以滑板之类的简单案例为例。您可能具有类似于以下内容的组件表

|---------------------|------------------|
|     id              |       Name       |
|---------------------|------------------|
|       1             |       Decks      |
|---------------------|------------------|
|       2             |       Wheels     |
|---------------------|------------------|
|       3             |       Trucks     |
|---------------------|------------------|

子组件

然后您可能会有一个类似于以下内容的子组件表

|---------------------|------------------|------------------|
|     id              |       Name       |   component_id   |
|---------------------|------------------|------------------|
|       1             |       Bearings   |        2         |
|---------------------|------------------|------------------|
|       2             |       Bushing    |        3         |
|---------------------|------------------|------------------|
|       3             |       Grip Tape  |        1         |
|---------------------|------------------|------------------|
|       4             |    Nuts / Bolts  |        1         |
|---------------------|------------------|------------------|

在这个简单的示例中,您可以在组件和子组件之间建立一对一和一对多的关系。 重要的是,不要将其与属性(我们尚未解决的属性)混淆。

属性

您的下一个抽象层是属性。通常,所有属性都与组件和子组件的表约束相关联,*并且它们不限于特定组合是否存在。

对于一个简化的示例,您可能有一个带有以下行的表属性

|---------------------|------------------|------------------|
|     id              |       Category   |      Value       |
|---------------------|------------------|------------------|
|       1             |       Size       |        7.5       |
|---------------------|------------------|------------------|
|       2             |       Size       |        7.75      |
|---------------------|------------------|------------------|
|       3             |       Size       |        6.25      |
|---------------------|------------------|------------------|
|       4             |      Brand       |    Toy Machine   |
|---------------------|------------------|------------------|
|       5             |      Brand       |    Bird House    |
|---------------------|------------------|------------------|
|       5             |      Brand       |      Nike        |
|---------------------|------------------|------------------|
|       5             |      Model       |     Nyjah Pro    |
|---------------------|------------------|------------------|
|       5             |      Model       |  Vice Monster    |
|---------------------|------------------|------------------|
|       6             |    ABEC Rating   |     class 6      |
|---------------------|------------------|------------------|
|       7             |    ABEC Rating   |     class 3      |
|---------------------|------------------|------------------|

您可以看到此表的约束方式与您的产品主要和次要产品不同(但是,这过于简化了,您显然会使用业务键代替属性标签,例如 ABEC)评分,等等。它列出了所有属性。

表达式

最后,您将有一个表达式表。这些表达式将作为行存储在表中。它们可能与其他表达式(递归键)有关,但不应与表有关。而是,它们应混合使用布尔逻辑,预定义函数和以前表中的替代键来指定可用的实际配置。这些通常不可重用(但可以与递归键结合使用,以提高可重用性)。

那里有各种各样的表达语言,有些是专有的,有些是开放的。我管理着一个定制的产品配置模型,该模型使用DMN(来自带给您BPMN的人)来表达我的陈述。

此外,我似乎有人在使用XML,XSLT和XPath代替上面列出的关系模型。表达式行可能类似于以下内容

(/component/id@1  & (/attribute/@id == 6 | /attribute/@id == 7))

总结

像任何软件系统一样,抽象是关键。我已经看到几乎所有的CPQ和产品配置模型都可以归结为这4个抽象(介于它们之间的数百个其他抽象)。除非是学术活动,否则我强烈建议您找到一个COT解决方案。足够了解您的产品以在主要属性,次要属性和属性之间进行抽象是关键,但是面包和黄油(不幸的是,“最不干净”的部分绝对是您存储在表中的表达语言)。

答案 1 :(得分:1)

存储所有组合并不是一个坏主意。但是,您也可以使用通配符。您的情况如下:

style                   size     color     price
NULL                    NULL     green     $1
collared                large    blue      $2
short sleeve            NULL     red       $3
long sleeve, collared   NULL     red       $4

如果您只有几个不同的价格,那么这可能还可以。但是,查询这种表的效率要比针对每种组合扩展表的效率低。