数据库设计:如何为产品/服务的通用价格因素建模?

时间:2011-03-02 22:39:31

标签: mysql database database-design

我正在尝试创建一个通用数据模型,允许特定产品(由下面的示例表中的FK product_id指示)指定0或更多价格“因子”(我将“因子”定义为一个单位增加或减去的价格以获得总数。)

所以说有这张表:

===============================
price
===============================
price_id (PK)
product_id (FK)
label
operation (ENUM: add, subtract)
type (ENUM: amount, percentage)
value

书的价格可能用这种方式表示:

====================================================================
price_id | product_id | label      |  operation | type       | value
====================================================================
 1       | 10         | Price      | add        | amount     | 20  
 2       | 10         | Discount   | subtract   | percentage | .25  
 3       | 10         | Sales Tax  | add        | percentage | .1

这基本上意味着:

Price:      $20.00
Discount:  - $5.00 (25%)
--------------------
Sub Total:  $15.00
Sales Tax:   $1.50 (10%)
------------------------
Total:      $16.50

几个问题:

  1. 初始设计有什么明显错误吗?
  2. 如果我想创建“模板”(例如具有“价格”,“折扣”和“销售税”字段的“一般商品”模板,具有“价格”,“折扣”的“奢侈品”, “奢侈税”领域) - 我将如何建模呢?
  3. 如果每条记录适用于前一记录的总数,则上述模型有效。因此,在该示例中,“销售税”适用于“价格”和“折扣”的差异。如果总计没有简单计算怎么办?例如:A + B +(A + 10%) - (B - 5%)。我该如何建模呢?
  4. 此外,如果“百分比”类型不适用于紧接在前的行(如问题#3所示)并应用于多于一行,该怎么办?我是否需要另一张表来逐项列出哪个价格> price_id适用于该百分比?

5 个答案:

答案 0 :(得分:6)

首先,您需要一个价格标签模型,这很简单:

price_labels
 id | label 
  1 | Price 
  2 | Discount 
  3 | Tax

然后是您提供的示例表的略微修改版本:

products_prices
price_id|product_id|label_id|divider|value 
  1         10        1        1      20 
  2         10        2        100   -25 
  3         10        3        100    10 

这里我只是将标签替换为 price_labels 表中相应的 id 作为外键。另外,我省略了 type 字段,这是微不足道的,因为值可以是正浮点数或负浮点数。我添加了divider列以启用百分比参数。我认为它也更容易以这种方式阅读,因为你说(并且认为)“减去百分之二十五”而不是0.25。

现在表达“抽象”部分有点复杂,可能有很多解决方案。

price_expressions
product_id | date_from          | date_until          | expression
  10       |2011-11-02 04:00:00 |2011-11-12 04:00:00  | (SELECT divider*value from 
                                                         products_prices 
                                                         WHERE product_id=%PRODUCT_ID%    
                                                         AND label_id=1)*
                                                        (SELECT 1+value/divider from products_prices 
                                                         where product_id=%PRODUCT_ID% AND 
                                                         label_id=2)*
                                                        (SELECT 1+value/divider from products_prices 
                                                         where product_id=%PRODUCT_ID% AND                                  
                                                         label_id=3)

在表达式字段中,您可以存储一个复杂的SQL语句,您可以在其中将%PRODUCT_ID%占位符替换为同一行中的product_id值:

SELECT REPLACE(expression,'%PRODUCT_ID%',CAST(product_id AS char)) 
AS price_expression FROM price_expressions 
WHERE product_id = 10 AND date_from>=DATE_OF_PURCHASE 
AND date_until<=DATE_OF_PURCHASE

我看到它的方式有两种可能的变化:

  1. 您可以仅使用price_id = N更改product_id =%PRODUCT_ID%和label_id = N 条件,因为您已将其存储在products_prices表中
  2. 您可以使用其他表达式格式,例如%PRICE_ID_1%*%PRICE_ID_2并在应用程序级别上执行替换和计算而不是直接在SQL中
  3. 希望这有帮助。

答案 1 :(得分:5)

这似乎有点过度设计。

1)销售税率不是购买商品的地方因素而不是购买商品的因素吗?我可以看到“IsTaxable”字段,但是指定每个项目的速率似乎不正确。

2)你确定需要承担制作这种通用的费用吗?您是否已经相当确定将来会有更多因素?如果没有,请不要过度复杂化。

推荐设计
  - 在产品表中为IsTaxable,DiscountPct和Unit Price添加列   - 将销售税百分比存储在另一个表中。可能是发票表。

答案 2 :(得分:2)

关于问题1

labeloperationtype之间存在潜在的功能依赖关系。例如,折扣可能总是暗示减法百分比。如果是这样,可以通过将这些字段移动到以label作为PK的单独表格来规范化数据模型。

BTW,非规范化数据模型可能是提高性能和/或简单性的合法工具。

关于问题2

这是一个允许轻松“模板化”的模型:

enter image description here

按照STEP_NO定义的顺序,按PRICE应用一系列步骤计算产品的最终价格。多个产品可以轻松共享相同的“模板”(即相同的PRICE_ADJUSTMENT_ID)。

关于问题3和4

您需要为完整的表达式树建模,而不仅仅是“线性”系列步骤。有几种方法可以做到这一点,其中大多数方法在关系范式中相当复杂。也许最简单的方法是保持数据模型与上面类似,但将其视为Reverse Polish Notation

例如......

A + B + (A + 10%) - (B - 5%)

......可以表示为:

OPERATION    TYPE       VALUE
----         ----       -----
             value      A
             value      B
add
             value      A
             percentage 10
add
add
             value      B
             percentage 5
subtract
subtract

您确定您确实需要这种功能吗?

答案 3 :(得分:0)

如果某些价格因素取决于商品的类型,那么您将有一组价格因素链接到ItemType表中的实体,而ItemType将是商品实体的属性(外键引用ItemType) 。如果其他价格因素与销售或运输物品的区域设置(例如销售税)相关联,则这些因素将链接到区域设置,并将根据客户的地址进行调用。您通常会在项次料品级别应用料品类型因子,并将区域设置驱动因素应用于发票总额。 Sin-tax将链接到ItemTypeLocale dyad,并应用于订单项级别。

答案 4 :(得分:0)

1 /我认为你还需要考虑序列

e.g。价格 - 折扣+销售税显然是可以接受的,但价格+销售税 - 折扣不是价格 - (折扣+销售税)

2 /我会考虑在另一张桌子上买价。这不是出售物品的细节吗?例如。小工具,蓝色,20.00美元。而您的因素是销售类型的细节。据推测,您可以为步入式零售提供一组因素,另一组用于在线销售,第三组用于批发销售。您可以从基本价格*因素计算这三种销售类型的实际价格。

3 /我认为你需要更多的桌子;例如也许是Item,Sale类型,factor_details和factor_rules。可能是您的销售类型由您的奢侈品项目的例子涵盖(在这种情况下(如果某个项目只是一种销售类型),这可能在项目表中。 Factor_rules将详细说明计算公式,factor_details值。

我发现这非常有趣。感谢您在完成此任务后,根据自己的经验更新此问题。