7

一部のカテゴリに属する​​製品がいくつかあります。

各カテゴリは異なるプロパティを持つことができます。

例えば、

  • カテゴリの車には、 color、power などのプロパティがあります。
  • カテゴリのペットには、 weightageなどのプロパティがあります 。

カテゴリの数は約 10 ~ 15 です。各カテゴリーの物件数は3~15物件。商品数は非常に多いです。

このアプリの主な要件は、非常に優れた検索です。カテゴリを選択し、このカテゴリの各プロパティの基準を入力します。

このシナリオのデータベースを設計する必要があります。(SQL サーバー 2005)

4

8 に答える 8

16

古典的な設計アプローチは次のようになります (星印は主キー列を示します)。

Product
  ProductId*
  CategoryId: FK to Category.CategroyId
  Name

Category
  CategoryId*
  Name

Property
  PropertyId*
  Name
  Type

CategoryProperty
  CategoryId*: FK to Category.CategoryId
  PropertyId*: FK to Property.PropertyId

ProductProperty
  ProductId*: FK to Product.ProductId
  PropertyId*: FK to Property.PropertyId
  ValueAsString

すべてのプロパティ値が文字列として DB に送られ、型変換情報が Property テーブルに格納されるという事実を受け入れることができる場合は、このレイアウトで十分です。

クエリは次のようになります。

SELECT
   Product.ProductId,
   Product.Name AS ProductName,
   Category.CategoryId,
   Category.Name AS CategoryName,
   Property.PropertyId,
   Property.Name AS PropertyName,
   Property.Type AS PropertyType,
   ProductProperty.ValueAsString
FROM
   Product 
   INNER JOIN Category         ON Category.CategoryId = Product.CategoryId
   INENR JOIN CategoryProperty ON CategoryProperty.CategoryId = Category.CategoryId
   INNER JOIN Property         ON Property.PropertyId = CategoryProperty.PropertyId
   INNER JOIN ProductProperty  ON ProductProperty.PropertyId = Property.PropertyId
                                  AND ProductProperty.ProductId = Product.ProductId
WHERE
   Product.ProductId = 1

指定する WHERE 条件が多いほど (AND を使用するなど、結合的に)、クエリは高速になります。テーブルに適切にインデックスを付けていれば、そうです。

このままでは、このソリューションは全文索引付けの状況には理想的ではありません。ここでは、ProductId に関連付けられたすべてのテキストをより非正規化された方法で格納する追加のテーブルが役立ちます。このテーブルは、ProductProperty テーブルの変更をリッスンするトリガーを通じて更新する必要があります。

于 2008-10-21T12:17:49.253 に答える
8

アプリケーションのユーザーが検索する前にカテゴリを選択する必要がある場合は製品をカテゴリごとに異なるデータベース テーブルに分けます。この解決策は、カテゴリ自体に共通点がほとんどないという事実によっても示されます。ユーザーがペットを探しているときに車を検索する時間が無駄にならないため、カテゴリ別に分類すると、各検索も大幅に高速化されます。

製品をカテゴリに分割したら、各カテゴリの製品の共通プロパティを使用してテーブルを簡単に作成できます。ユーザーがカテゴリを選択すると、ユーザーが選択できるプロパティが変化する必要があるため、アプリケーションのユーザー インターフェイスは動的である必要があります (私は Web フォームを考えています)。

複数のカテゴリにリストしたい製品がある場合、この解決策では表に重複データが生じることに注意してください。データベースを設計する場合、速度と正規化の間にはトレードオフがあります。複数のカテゴリに当てはまる商品がない場合は、これが(検索速度の点で)最速のソリューションになると思います。

于 2008-10-21T12:02:12.467 に答える
2

ほとんどの人は、Entity-Attribute-Value (EAV) 設計のバリエーションを使用することを勧めています。この設計はあなたの状況ではやり過ぎであり、多くの問題を引き起こします。次に例を示します。

  • 属性のデータ型を定義することはできません。整数属性に「バナナ」を入力できます
  • 属性を必須として宣言することはできません (つまり、従来のテーブルでは NOT NULL です)。
  • 属性に対して外部キー制約を宣言することはできません

カテゴリの数が少ない場合は、Bogdan Maxim の回答でソリューション A を使用することをお勧めします。つまり、カテゴリ固有の属性を格納するために、すべてのカテゴリに共通の属性を持つテーブル Products を 1 つ定義し、カテゴリごとに追加のテーブルを 1 つ定義します。

無限の数のカテゴリがある場合、または Products の行ごとに異なる属性セットをサポートする必要がある場合にのみ、EAV は適切なソリューションです。しかし、EAV は正規化のいくつかの規則に違反しているため、リレーショナル データベースをまったく使用していません。

それだけの柔軟性が本当に必要な場合は、データを XML に格納する方がよいでしょう。実際、RDF やSesameなどのセマンティック Web フレームワークを検討することもできます。

于 2008-10-21T17:02:41.080 に答える
1

もっとオブジェクト指向の何かを試すことができます。

1.製品のベーステーブルを定義します

Products(ProductID, CategoryID, <any other common properties>)

2.テーブルカテゴリを定義します

Categories(CategoryID, Name, Description, ..)

ここから多くのオプションがあり、それらのほとんどすべてがデータベースの正規化を破ります。

解決策A。

新製品を追加する必要がある場合は、メンテナンスの悪夢になります

A1。カテゴリごとに個別のテーブルを定義します

Cars(CarID, ProductID, ..) Pets(PetID, ProductID, ..)

A2。データを使用するために、関係に基づいてテーブルを結合します

SELECT <fields> FROM Cars INNER JOIN Products ON Cars.ProductID = Products.ProductID

解決策B。

さまざまなタイプのプロパティ(int、varcharなど)のメンテナンスの悪夢

B1。プロパティのテーブルを定義する

CategoryProperty (CPID, Name, Type)

B2。カテゴリとプロパティ間の関連付けを保持するテーブルを定義します

PropertyAssociation (CPID, PropertyID)

B12。プロパティを保持するテーブルを定義します(B1およびB2の代替)

Properties(CategoryID, PropertyID, Name, Type)

B3。プロパティのタイプ(int、double、varcharなど)ごとに、値テーブルを追加します

PropertyValueInt(ProductID, CPID, PropertyID, Value)-int PropertyValueString(ProductID, CPID, PropertyID, Value)の場合-文字列 PropertyValueMoney(ProductID, CPID, PropertyID, Value)の場合-お金の場合

B4。すべてのテーブルを結合して、目的のプロパティを取得します。

このアプローチを使用することにより、すべてのプロパティを個別のテーブルで管理する必要はありませんが、それらの値タイプを管理する必要があります。基本的に、関連するすべてのテーブルはルックアップテーブルになります。欠点は、各値を取得するために、すべての値タイプに対して「ケース」を指定する必要があることです。

これらのアプローチのいずれかを選択するときは、これらの記事(ここここ)を覚えておいてください。このフォーラムの投稿も興味深いものであり、ローカリゼーションに関するものですが、何らかの形で主題に関連しています。

Tomalakの答えを使用して、必要に応じて強い型付けを追加することもできます。

于 2008-10-21T13:03:47.710 に答える
1

各製品に属性の任意の名前/値のペアで「タグ付け」できる、 Entity-Attribute-Valueタイプの配置を検討することをお勧めします。

于 2008-10-21T12:05:52.037 に答える
1

これを試すことができます。あなたの質問の実際の詳細についてはあまり確信が持てません。

5テーブル。3 つはデータを格納するため、2 はデータ間のマッピングを格納するためです。

tProduct 
  productID
  <other product details>

tCategory
  categoryID
  <other category details>

tProperty
  propertyID
  <other property details>

tProductXCategory
  productyID
  categoryID

tCategoryXProperty
  categoryID
  propertyID

クエリでは、マッピング テーブルを使用してデータを結合する必要がありますが、これにより、カテゴリ、プロパティ、および製品の間にさまざまな多対多の関係を持たせることができます。

ストアド プロシージャまたはパラメーター化されたクエリを使用して、検索のパフォーマンスを向上させます。

于 2008-10-21T12:08:16.947 に答える
0

私は最近これをしなければなりませんでした.3つのエンティティがあるNHibernateを使用しています

製品カテゴリ オプション OptionCategory

製品には 1* カテゴリがあります

製品には 1* オプションがあります

オプションには 1 つの OptionCategory があります

これが設定されると、Nhibernate キャッシュを使用できます

乾杯

于 2008-10-21T13:09:01.427 に答える
0

カテゴリとプロパティに柔軟性を持たせたい場合は、次のテーブルを作成する必要があります。

  • 製品: 製品 ID
  • カテゴリ: カテゴリ ID、製品 ID
  • プロパティ: PropertyID、CategoryID

複数の製品でカテゴリを共有する場合は、n:m 結合用のリンク テーブルを作成する必要があります。

  • productCategoryPointer: ProdCatID、ProductID、CategoryID。

クエリでいくつかの結合が必要になりますが、適切なインデックスがあれば、データをすばやくクエリできるはずです。

于 2008-10-21T12:10:16.973 に答える