Дизайн базы данных: как смоделировать общие ценовые факторы продукта / услуги? - PullRequest
14 голосов
/ 03 марта 2011

Я пытаюсь создать общую модель данных, которая позволит конкретному товару (указанному 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) и применяется к более чем 1 строке?Нужна ли мне еще одна таблица, чтобы указать, к какой цене-> цене_идентификатора относится процент?

Ответы [ 5 ]

6 голосов
/ 05 ноября 2011

Прежде всего вам нужна модель ценников, которая проста:

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 

Здесь я просто заменил метку соответствующим id из таблицы price_labels в качестве внешнего ключа. Кроме того, я пропустил поле type , которое тривиально, поскольку значение может быть положительным или отрицательным числом с плавающей точкой. Я добавил столбец делителя, чтобы включить процентный параметр. Я думаю, что так легче читать и так, поскольку вы говорите (и думаете) «минус двадцать пять процентов», а не 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. Вы можете изменить условие product_id =% PRODUCT_ID% и label_id = N , указав только price_id = N, поскольку оно уже сохранено в таблице products_prices
  2. Вы можете использовать другой формат выражения, например, % PRICE_ID_1% *% PRICE_ID_2 и выполнять подстановки и вычисления на уровне приложения, а не непосредственно в SQL

Надеюсь, это поможет.

5 голосов
/ 03 марта 2011

Это кажется немного перегруженным.

1) Разве процент с налога с продаж не будет зависеть от того, где товар был куплен, а не от того, какой предмет был куплен? Я мог видеть поле для «IsTaxable», но указание скорости для каждого элемента кажется неправильным.

2) Вы уверены, что вам нужно нести стоимость изготовления этого дженерика? Вы уже уверены, что в будущем будет больше факторов? Если нет, не переусердствуйте.

Предлагаемый дизайн :
- Добавьте столбцы в таблицу продуктов для IsTaxable, DiscountPct и Цена за единицу.
- Сохраните процент налога с продаж в другой таблице. Вероятно, таблица счетов.

2 голосов
/ 10 ноября 2011

Относительно вашего вопроса 1 :

Существует потенциальная функциональная зависимость между label, operation и type.Например, скидка всегда может подразумевать вычитание и процент .Если это так, модель данных может быть нормализована путем перемещения этих полей в отдельную таблицу с label в качестве PK.

Кстати, ненормализованная модель данных может быть законным инструментом для повышения производительности и / илиПростота.

Относительно вашего вопроса 2 :

Вот модель, которая позволяет легко "шаблонизировать":

enter image description here

Окончательная цена продукта рассчитывается путем применения последовательности шагов в PRICE в порядке, определенном STEP_NO.Несколько продуктов могут легко использовать один и тот же «шаблон» (т. Е. Один и тот же PRICE_ADJUSTMENT_ID).

Относительно ваших вопросов 3 и 4 :

Вам необходимо смоделировать полныйдерево выражений, а не просто «линейный» ряд шагов.Есть несколько способов сделать это, большинство из них довольно сложны в реляционной парадигме.Возможно, самый простой способ - сохранить модель данных, аналогичную описанной выше, но обработать ее как Обратное польское обозначение .

Например ...

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

Вы действительно нуждаетесь в такой функциональности?

0 голосов
/ 03 марта 2011

1 / Я думаю, вам также нужно учитывать последовательность

например. Цена - скидка + налог с продаж, очевидно, приемлема, но Цена + налог с продаж - скидка не является и Цена - (скидка + налог с продаж)

2 / Я хотел бы рассмотреть вопрос о наличии цены в другой таблице. Разве это не деталь продаваемого товара? Например. Виджет, синий, 20,00 $. В то время как ваши факторы являются деталью типа продаж. Предположительно, у вас может быть один набор факторов для розничной продажи, другой для онлайн-продажи и третий для оптовой продажи. Вы можете рассчитать фактическую цену для этих трех типов продажи из коэффициентов базовой цены *.

3 / Я думаю, вам нужно больше столов; например может быть Предмет, Тип продажи, а также factor_details и factor_rules. Может случиться так, что ваш тип продажи охватывается вашим примером предмета роскоши, и в этом случае (если предмет имеет только один тип продажи), это может быть в таблице предметов. Factor_rules будет детализировать формулу расчета, а factor_details значения.

Я нахожу это довольно интересным. Буду признателен за обновление этого вопроса вашим опытом, как только вы проработаете этот вопрос.

0 голосов
/ 03 марта 2011

Если некоторые ценовые факторы зависят от типа элемента, то у вас будет набор ценовых факторов, связанных с объектами в таблице ItemType, а ItemType будет свойством объекта элемента (внешний ключ ссылается на ItemType) , Если другие ценовые факторы связаны с языковым стандартом, в котором товар продается или поставляется (например, налог с продаж), то эти факторы будут связаны с языковым стандартом и будут вызываться на основании адреса клиента. Обычно вы применяете факторы типа элемента на уровне позиции и факторы, определяемые локалью, к итоговой сумме счета. Налог на прибыль будет связан с диадой ItemTypeLocale и применяется на уровне позиции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...