我最近一直在打印店网站上工作。而且我现在在开发有效的数据库模式方面遇到了麻烦。
我的应用程序是一家打印店,它为海报、名片和传单等提供定制打印品。
我面临的问题是开发产品选项的架构。
这是一个场景:
名片可以有“尺寸”和“ Material ”选项。 “尺寸”可以是“3.5x2.5 英寸”或“3.25x2.25 英寸”。同样,“ Material ”可以是“300 gsm Card Stock”或“200 gsm Card Stock”。
现在我的商店提供的是选项和数量组合的价格。
喜欢,100 Business Cards + 3.5x2.5 inch + 300 gsm Card Stock = $500.00
要么200 Business Cards + 3.5x2.5 inch + 300 gsm Card Stock = $800.00
.
这里需要注意的一点是,“传单”和“海报”产品的“尺寸”选项是不同的。所以“3.5x2.5”海报是没有意义的。海报产品将有自己的尺寸。价格始终与期权组合绑定(bind),没有期权组合的产品没有单独的价格。
其次,也有基于重量的运输。所以我也想知道,权重在数据库中存储在哪里?
请提供一些关于设计这样一个数据库的见解。我也想要一种基于 ActiveRecord 的方法,因为我在 EAV 建模方面太弱了。
最佳答案
你可以这样做:
Products
:
ProductId
主键,ProductName
, Materials
:MaterialID
主键,MaterialName
. Units
:UnitId
主键,UnitName
. ProductsSizesOptions
:SizeOptionId
主键,Height
, Width
, UnitId
外键约束 REFERENCES Units(UnitId)
为每种产品处理不同类型的单元。 ProductsMaterialOptions
:MaterialOptionId
, Quantity
, MaterialId
外键约束 REFERENCES Materials(MaterialId)
为每种产品的报价处理不同类型的 Material 。 ProductsOffers
:OfferId
主键,ProductId
外键约束 REFERENCES Products(ProductId)
, MaterialOptionId
外键约束 REFERENCES ProductsMaterialOptions(MaterialOptionId)`, SizeOptionId
外键约束 REFERENCES ProductsSizesOptions(SizeOptionId)
, Price
. 例如,对于您在问题中发布的示例数据,您可以通过
JOIN
简单地获取每种产品的这些优惠。表格:SELECT
po.OfferId,
p.ProductNAme,
mo.Quantity,
m.MaterialName,
so.Height,
so.width,
u.UnitName,
po.Price
FROM products AS p
INNER JOIN ProductsOffers AS po ON p.ProductId = po.ProductId
INNER JOIN ProductsMaterialOptions AS mo ON po.MaterialOptionId = mo.MaterialOptionId
INNER JOIN ProductsSizesOptions AS so ON so.SizeOptionId = po.SizeOptionId
INNER JOIN Units AS u ON u.UnitId = so.unitId
INNER JOIN Materials AS m ON m.MaterialId = m.MaterialId;
这会给你类似的东西:
| OFFERID | PRODUCTNAME | QUANTITY | MATERIALNAME | HEIGHT | WIDTH | UNITNAME | PRICE |
-----------------------------------------------------------------------------------------
| 1 | Business Card | 100 | Card Stock | 4 | 3 | gsm | 500 |
| 2 | Business Card | 200 | Card Stock | 4 | 3 | gsm | 800 |
然后从您的前端应用程序中,您可以按照您希望的方式格式化这些结果。
SQL Fiddle Demo For DB schema
更新
Products
: ProductId
, ProductName
, Options
: OptionId
, OptionName
. 要存储可能的选项:
OptionId OptionName
1 Material
2 Shape
and so on
Properties
: PropertyId
, PropertyName
, PropertyTypeId
. PropertiesTypes
: PropertyTypeId
, PropertyTypeName
. 您可能不需要此表,但您可以在前端应用程序中使用它来了解如何在应用程序中显示此字段。例如,它可能包含以下值:
1 Integer
2 String
3 Decimal
...
OptionsProperties
: OptionPropertyId
, OptionId
, PropertyId
. 每个选项的属性,例如
Shape
和 Material
:OptionPropertyId OptionId PropertyId
1 1 1
2 2 2
3 2 3
4 2 4
ProductOptions
: ProductOptionId
, ProductId
, OptionId
. ProductOptionsValues
: ProductOfferOptionsId
, ProductId
, PropertyId
, NumericValue
, TXTValue
. ProductsOffers
: OfferId
, ProductOfferOptionsId
, Quantity
, Price
. 因此您可以获得每个产品的报价列表,如下所示:
SELECT
p.ProductName,
MAX(CASE WHEN pr.PropertyName = 'Material Name' THEN PropertyValue END) AS 'Material Name',
MAX(CASE WHEN pr.PropertyName = 'Height' THEN PropertyValue END) AS 'Height',
MAX(CASE WHEN pr.PropertyName = 'Width' THEN PropertyValue END) AS 'Width',
MAX(CASE WHEN pr.PropertyName = 'Unit' THEN PropertyValue END) AS 'Unit',
o.Quantity,
o.Price
FROM products AS p
INNER JOIN
(
SELECT
ProductId,
PropertyId,
ProductOfferOptionsId,
COALESCE(NumericValue, TXTValue) AS PropertyValue
FROM
ProductOptionsValues
) AS ov ON ov.ProductId = p.ProductId
INNER JOIN OptionsProperties AS op ON op.PropertyId = ov.PropertyId
INNER JOIN Properties AS pr ON op.PropertyId = pr.PropertyId
INNER JOIN ProductsOffers AS o ON o.ProductOfferOptionsId = ov.ProductOfferOptionsId
GROUP BY p.ProductName,
o.Quantity,
o.Price;
这会给你:
| PRODUCTNAME | MATERIAL NAME | HEIGHT | WIDTH | UNIT | QUANTITY | PRICE |
-----------------------------------------------------------------------------
| Business Card | gsm Card Stock | 3.5 | 2.5 | inch | 100 | 500 |
| Business Card | gsm Card Stock | 3.5 | 2.5 | inch | 200 | 800 |
SQL Fiddle Demo
当然,这个查询没有意义。要获取所有属性的列表,您必须使用动态 SQL 动态执行此操作。您可以将以下代码放入存储过程中:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(pr.PropertyName = ''',
pr.PropertyName, ''', ov.PropertyValue, 0)) AS ', '''', pr.PropertyName , '''')
) INTO @sql
FROM Properties AS pr
INNER JOIN
(
SELECT
PropertyId,
COALESCE(NumericValue, TXTValue) AS PropertyValue
FROM
ProductOptionsValues
) AS ov ON pr.PropertyId = ov.PropertyId;
SET @sql = CONCAT('SELECT
p.ProductName, ', @sql , ', o.Quantity,
o.Price
FROM products AS p
INNER JOIN
(
SELECT
ProductId,
PropertyId,
ProductOfferOptionsId,
COALESCE(NumericValue, TXTValue) AS PropertyValue
FROM
ProductOptionsValues
) AS ov ON ov.ProductId = p.ProductId
INNER JOIN OptionsProperties AS op ON op.PropertyId = ov.PropertyId
INNER JOIN Properties AS pr ON op.PropertyId = pr.PropertyId
INNER JOIN ProductsOffers AS o ON o.ProductOfferOptionsId = ov.ProductOfferOptionsId
GROUP BY p.ProductName,
o.Quantity,
o.Price');
prepare stmt
FROM @sql;
execute stmt;
Updated SQL Fiddle Demo
这将动态地旋转所有属性。
关于mysql - 在数据库模式设计方面需要帮助以获取打印厂产品选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15631807/