#sql #diagram
#sql #схема
Вопрос:
Я пытаюсь спроектировать базу данных, которая включает продукты, типы продуктов, атрибуты продукта, в которой также хранятся стоимость и запасы (inventory). Я бы хотел, чтобы это имело как можно меньше const / hardcoding, а также было масштабируемым в будущем.
Проблема, с которой я сталкиваюсь, заключается в том, что я хотел бы иметь несколько атрибутов, привязанных к продукту, некоторые из атрибутов привели бы к увеличению стоимости продукта, и вести инвентаризацию продукта со всеми этими атрибутами.
Вот моя текущая схема базы данных:
Я думал о добавлении столбца ‘ProductAttributeID’ в таблицы ProductPricing и Product Stock / Supply.
Это сработало бы для одного атрибута, но не в том случае, если бы учитывались два.
ie:
Product = Shirt
Attribute = Size (small, medium, large)
Attribute#2 = Color (red, green, blue)
...
Я полагаю, я мог бы создать таблицу ProductAttributeModifier, чтобы добавлять / вычитать / делить / умножать значение на общее значение.
ProductAttributeModifier
========================
ProductAttributeID (bigint) FK_,
Operator (char(1)), // , -, *, /, %
CostValue decimal(7,2)
Таким образом, я мог бы составить сводную информацию об общей стоимости продукта с несколькими атрибутами.
Есть ли какие-либо подводные камни в этом методе?
Как бы я поступил с поставкой продуктов? Я думал о добавлении нескольких столбцов в качестве ограничений внешнего ключа для разных атрибутов ProductAttributes, но это не масштабируемо и требует будущих знаний о продукте.
Возможно, будет ли другая таблица работать как соединение с отдельным количеством? С повторением всех атрибутов? Есть ли подводные камни и в этом методе?
ProductAttributeSupply
======================
ProductSupplyId (bigint) FK_,
AttributeID (bigint) FK_,
Quantity (int/bigint)
Было бы разумнее поместить общую совокупность поставок в view / sproc?
Я ожидаю, что диаграмма будет обрабатывать следующие сценарии:
- Продукт без одного или нескольких атрибутов
- Будьте готовы к атрибутам, изменяющим стоимость (от средней до большой)
- Должен ли модификатор стоимости быть необязательным
- Рассчитайте необходимое количество продукта со всеми атрибутами, соответствующими нашему инвентарю
- Правильно сохраняйте количество продуктов, соответствующих каждому атрибуту, когда мы получаем в нашей базе данных. ‘ProductStock’
Комментарии:
1. Этот вопрос лучше задать на дочернем сайте: dba.stackexchange.com
Ответ №1:
Ваш ProductAttributeModifier
подход мог бы сработать, но я не понимаю, зачем вам нужно что-то менять в отношении поставок.
Products:
- 1: small green shirt
- 2: large green shirt
Attributes:
- 1: size
- 2: color
ProductAttributes (ProductId, AttributeId):
- (1, 1) small
- (1, 2) green
- (2, 1) large
- (2, 2) green
Вам не нужны атрибуты в вашем складе / поставке, у вас просто есть количества на маленьких зеленых рубашках и больших зеленых рубашках, верно?
Если вы хотите, чтобы атрибуты изменяли базовую цену, просто используйте FK ProductPricing
в ProductType
(«рубашка») и получите представление, которое рассчитает цену продукта на основе цены типа атрибуты, скажите что-то вроде:
CREATE VIEW vProductWithPrice
AS
SELECT p.Id
, (pp.Price
SUM(CASE av.PriceModifierOperator
WHEN '-' THEN -av.PriceModifierValue
WHEN ' ' THEN av.PriceModifierValue
WHEN '%' THEN pp.Price * av.PriceModifierValue / 100.0
ELSE 0
END)
) AS Price
FROM Products p
JOIN ProductTypes pt
ON p.ProductTypeId = pt.ProductTypeId
JOIN ProductPricing pp
ON pp.ProductTypeId = pt.ProductTypeId
AND pp.TerminationDate IS NULL -- currently active
JOIN ProductAttributes pa
ON pa.ProductId = p.ProductId
JOIN AttributeValue av
ON av.AttributeValueId = pa.AttributeValueId
GROUP BY p.Id, pp.Price
Здесь я использую что-то вроде AttributeValue
с полями типа:
- AttributeValueId
- AttributeId (link to e.g. size)
- Value (small/large/etc.)
- PriceModifierOperator ( , -, %)
- PriceModifierValue
Имейте в виду, что выполнение таких операторов, как *
или /
, потребует действительно тяжелой работы, потому что:
- необходимо учитывать порядок (вы применяете только базовую цену или после атрибутов, или, может быть, после некоторых атрибутов, но перед другими; в конце концов 5 * 3 1 2 != (5 1) * 3 2 != (5 1 2) * 3; и
- объединение нескольких операторов * было бы проблемой, вы не можете просто сделать
BasePrice * SUM(value)
, если один равен * 2, а другой равен * 3, тогда вы получитеBasePrice * 5
вместоBasePrice * 6
, и есть предостережения при использованииEXP(SUM(LOG(Value)))
Комментарии:
1. Я бы предположил, что мне понадобятся атрибуты на складе / инвентаризации. Я предполагал, что у меня может быть один продукт «рубашка» с атрибутами «размер» и «цвет». Вы бы сказали, что лучше создавать отдельные продукты для нескольких атрибутов? (Я представляю выпадающий список выбора для «рубашки» в представлении продукта). Мне нравится то, что вы думаете о представлении модификатора атрибута продукта. Также хорошо звучит для операторов * /, я думаю, у меня все равно нет реального приложения для них.
2. Я бы сказал, что определенно лучше иметь все варианты продукта в виде отдельных продуктов, у вас есть тип продукта в качестве родительского, если вы хотите их сгруппировать, категории также могут быть привязаны к типу, если это необходимо. Чрезмерно сложная схема усложнит работу с ней как людям, запрашивающим базу данных, так и разработчикам приложений, которые будут сохранять в ней данные. По моему опыту, чрезмерное проектирование с целью бесконечной гибкости очень часто приводит к обратным результатам.