0

私は最近、プリントショップのウェブサイトに取り組んでいます。そして今、効率的なデータベース スキーマの開発に苦労しています。

私のアプリケーションは、ポスター、名刺、チラシなどのカスタム プリントを提供する Printshop です。私が直面している問題は、製品オプションのスキーマを開発することです。シナリオは次のとおりです。名刺には「サイズ」と「素材」のオプションがあります。「サイズ」は「3.5x2.5 インチ」または「3.25x2.25 インチ」です。同様に、「素材」は「300 gsm カード ストック」または「200 gsm カード ストック」です。今、私の店が提供しているのは、オプションと数量の組み合わせの価格です。

お気に入り、 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」のポスターは意味がありません。ポスター製品には独自のサイズがあります。価格は常にオプションの組み合わせに拘束されます。オプションの組み合わせのない製品には個別の価格はありません。

第二に、重量ベースの配送もあります。だから私も知りたいのですが、データベースのどこに重みを保存するのですか?

このようなデータベースの設計について、いくつかの洞察を提供してください。また、私は EAV モデリングが苦手なので、ActiveRecord ベースのアプローチを希望しています。

4

2 に答える 2

4

あなたはこれを行うことができます:

Products:

  • ProductId主キー、
  • ProductName
  • ...

Materials:

  • MaterialID主キー、
  • MaterialName.

Units:

  • UnitId主キー、
  • UnitName.

ProductsSizesOptions:

  • SizeOptionId主キー、
  • Height
  • Width
  • UnitIdREFERENCES Units(UnitId)製品ごとに異なるタイプのユニットを処理するための外部キー制約。

ProductsMaterialOptions:

  • MaterialOptionId
  • Quantity
  • MaterialIdREFERENCES Materials(MaterialId)各製品のオファーのさまざまなタイプのマテリアルを処理するための外部キー制約。

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 |

次に、フロントエンド アプリケーションから、これらの結果を希望どおりにフォーマットできます。

DB スキーマの SQL Fiddle デモ


アップデート

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 フィドルのデモ


もちろん、このクエリは意味がありません。すべてのプロパティのリストを取得するには、動的 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;

更新された SQL Fiddle デモ

これにより、すべてのプロパティが動的にピボットされます。

于 2013-03-26T09:06:27.973 に答える
2

カタログからアイテムを販売しています。アイテムは、商品 (実際には製品の仕様であり、物理的な資産ではありません)、またはマーケティング パッケージと呼ばれる商品のコレクションのいずれかです。

ここでテーブル継承を使用する必要があります。

catalog_item
------------
id
type {good, marketing_package}
name

good : catalog_item
-------------------
size
material

marketing_package : catalog_item
--------------------------------
standard_price

marketing_package_good (this is a junction table)
----------------------
marketing_package_id
good_id
quantity

poster : good
-------------
{any poster-specific properties or defaults}


flyer : good
------------
{any flyer-specific properties or defaults}


business_card : good
--------------------
{any business-card-specific properties or defaults}
于 2013-03-26T17:25:59.327 に答える