Frage

Ich habe einige Produkte, die zum einem gewissen Kategorie gehört.

Jede Kategorie kann unterschiedliche Eigenschaften haben.

Beispiel:

  • Kategorie Autos hat Eigenschaften Farbe , Macht, ...
  • Kategorie Haustiere haben Eigenschaften Gewicht Alter , ...

Die Anzahl der Kategorien ist etwa 10-15. Anzahl der Objekte in jeder Kategorie ist 3-15. Anzahl der Produkte ist sehr groß.

Hauptvoraussetzung für diese App ist sehr gut suchen. Wir werden Kategorie auswählen, und geben Sie Kriterien für jede Eigenschaft in dieser Kategorie.

Haben Datenbank für dieses Szenario zu entwerfen. (SQL Server 2005)

War es hilfreich?

Lösung

Das klassische Design-Ansatz wäre (der Stern bezeichnet die Primärschlüsselspalte):

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

Wenn Sie mit der Tatsache leben, dass jeder Eigenschaftswert die DB gehen würde als ein String und Typumwandlung Info in der Objekttabelle gespeichert ist, würde dieses Layout genug sein.

Die Abfrage würde wie folgt gehen:

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

Je mehr WHERE Bedingungen, die Sie liefern (verbindend, zum Beispiel unter Verwendung von AND), desto schneller wird die Abfrage sein. Wenn Sie richtig Ihre Tabellen indiziert haben, ist, dass.

Wie es ist, ist die Lösung für eine Volltextindizierung Situation nicht ideal. Eine zusätzliche Tabelle, die die gesamten Text im Zusammenhang mit einem ProductId in einer denormalisierter Weise speichert könnte hier helfen. Diese Tabelle würde durch Trigger zu aktualisieren ist, die für Änderungen in der Tabelle Product hören.

Andere Tipps

Wenn der Benutzer der Anwendung hat eine Kategorie auswählen, bevor sie suchen, würde ich Ihre Produkte in verschiedene Datenbanktabellen nach Kategorie trennen. Diese Lösung wird auch durch die Tatsache, dass die Kategorien sich gemeinsam so wenig haben. Bricht sie nach Kategorie nach unten wird jeweils auch viel schneller zu suchen, da Zeit mit der Suche durch Autos nicht verschwendet werden, wenn der Benutzer für ein Haustier suchen.

Wenn Sie die Produkte in Kategorien aufgeteilt haben, soll es einfach sein, die Tabellen in jeder Kategorie mit den gemeinsamen Eigenschaften der Produkte zu erstellen. Die Benutzeroberfläche der Anwendung sollte dynamisch sein (ich bin von einem Web-Formular zu denken), dass die Eigenschaften kann der Benutzer wählen sollte sich ändern, wenn der Benutzer eine Kategorie auswählt.

Bitte beachten Sie, dass, wenn Sie Produkte haben, die Sie in mehreren Kategorien aufgelistet werden sollen, wird diese Lösung in doppelten Daten in Tabellen führen. Es ist ein Kompromiss zwischen Geschwindigkeit und Normalisierung, wenn eine Datenbank zu entwerfen. Wenn Sie nicht haben Produkte, die mehrere Kategorien passen, dann denke ich, das die schnellste Lösung (in Bezug auf die Suchgeschwindigkeit) sein wird.

Die meisten Menschen Variationen des Entity-Attribut-Wert (EAV) Design verwenden beraten. Dieser Entwurf ist viel des Guten für Ihre Situation, und es stellt eine ganze Reihe von Problemen, zum Beispiel:

  • Sie können nicht Datentyp für ein Attribut definieren; Sie können „Banane“ für eine ganze Zahl Attribut eingeben
  • Sie können nicht ein Attribut als obligatorisch erklären (das heißt NOT NULL in einer herkömmlichen Tabelle)
  • Sie können keine Fremdschlüssel auf einem Attribut deklarieren

Wenn Sie eine kleine Anzahl von Kategorien haben, ist es besser, die Lösung A in Bogdan Maxim Antwort zu verwenden. Das heißt, mit Attributen eine Tabelle Produkte definieren, die für alle Kategorien, und eine zusätzliche Tabelle für jede Kategorie, die Kategorie-spezifische Attribute zu speichern.

Nur wenn Sie eine unendliche Anzahl von Kategorien haben oder wenn Sie möglicherweise einen anderen Satz von Attributen pro Zeile in Produkten unterstützen müssen, ist EAV eine gute Lösung. Aber dann verwenden Sie sind nicht eine relationale Datenbank überhaupt, da EAV mehrere Regeln der Normalisierung verletzt.

Wenn Sie wirklich brauchen, so viel Flexibilität, Sie wären besser dran, Ihre Daten in XML zu speichern. In der Tat könnte man in RDF aussehen und semantische Web-Frameworks wie Sesame .

Sie möchten vielleicht einen Entity-Attribute-Value Art betrachten Anordnung, wo Sie „Tag“ jedes Produkt mit beliebigen Namen / Wert-Paaren von Attributen.

Sie können dies versuchen. Ich bin nicht ganz sicher von den tatsächlichen Details Ihrer Frage kann vielleicht jemand helfen, ein wenig besser zu übersetzen.

5 Tabellen. 3 für die Daten, 2 zum Speichern der Zuordnungen zwischen Speichern von Daten.

tProduct 
  productID
  <other product details>

tCategory
  categoryID
  <other category details>

tProperty
  propertyID
  <other property details>

tProductXCategory
  productyID
  categoryID

tCategoryXProperty
  categoryID
  propertyID

Ihre Anfragen müssen die Daten mit Hilfe der Mapping-Tabellen verbinden, aber dies ermöglicht es Ihnen verschiedene viele zu viele Beziehungen zwischen Kategorie, Eigenschaften und Produkten zu haben.

Verwenden von gespeicherten Prozeduren oder parametrisierte Abfragen zu einem besseren Leistung aus Ihrer Suche zu erhalten.

Wenn Sie auf Ihren Kategorien und Eigenschaften flexibel sein wollen, sollten Sie folgende Tabellen erstellen:

  • Produkt: ProductID
  • Kategorie: CategoryID, ProductID
  • Eigenschaft: PropertyID, CategoryID

Wenn Sie eine Kategorie über mroe als ein Produkt teilen möchten, haben Sie eine Verknüpfungstabelle für die n erstellen: m verbinden:

  • productCategoryPointer. ProdCatID, ProductID, CategoryID

Sie werden müssen einige in Ihrer Abfrage beitritt, aber mit dem richtigen Indizes shoulb Sie in der Lage sein, Ihre Daten schnell abgefragt werden.

Sie könnten etwas mehr objektorientierte versuchen.

1. Definieren Sie eine Basistabelle für Produkte

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

2. Definieren Sie eine Tabelle Kategorien

Categories(CategoryID, Name, Description, ..)

Von hier aus haben Sie eine Menge von Optionen und fast alle von ihnen wird die Normalisierung der Datenbank brechen.

Lösung A.

Wird ein maintaince Alptraum sein, wenn Sie neue Produkte hinzufügen müssen

A1. Definieren Sie eine separate Tabelle für jede der Kategorien

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

A2. Verknüpfen Sie die Tabellen auf der Grundlage der Beziehungen, um die Daten zu verwenden

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

Lösung B.

Maintainance Schreckgespenst für verschiedene Arten von Eigenschaften (d.h. int, VARCHAR, etc)

B1. Definieren Sie eine Tabelle für die Eigenschaften

CategoryProperty (CPID, Name, Type)

B2. Definieren Sie eine Tabelle, die die Zuordnungen zwischen Kategorien und Eigenschaften

zu halten

PropertyAssociation (CPID, PropertyID)

B12. Definieren Sie eine Tabelle, die die Eigenschaften zu halten (Alternative für B1 und B2)

Properties(CategoryID, PropertyID, Name, Type)

B3. Für jede Art von Eigentum (int, double, varchar, etc.) eine Wertetabelle hinzufügen

PropertyValueInt(ProductID, CPID, PropertyID, Value) - für int PropertyValueString(ProductID, CPID, PropertyID, Value) - für Streicher PropertyValueMoney(ProductID, CPID, PropertyID, Value) - für Geld

B4. Verbinden Sie alle Tabellen, um die gewünschte Eigenschaft retreive.

Durch diesen Ansatz verwenden, werden Sie nicht alle Eigenschaften in separaten Tabelle zu verwalten haben, aber die Werttypen von ihnen. Grundsätzlich alle beteiligten Tabellen werden Lookup-Tabellen. Der Nachteil ist, dass, um jeden Wert zu retreive, müssen Sie „Case“ für jeden Werttyp.

Nehmen Sie diese Artikel in mind ( hier und hier ), wenn jeder dieser Ansätze wählen. diesem Forum erstellen ist auch interessant und irgendwie Zusammenhang mit dem Thema, auch obwohl es über die Lokalisierung.

Sie auch Tomalak Antwort und starke Typisierung hinzufügen, wenn Sie das Bedürfnis haben.

Vor kurzem hatte ich, dies zu tun, und ich verwende NHibernate, wo ich drei Entitäten

Produktkategorie Option OptionCategory

Ein Produkt hat 1 * Kategorien

Ein Produkt hat 1 * Option

Eine Option hat 1 OptionCategory

, sobald diese eingerichtet ist, können Sie Nhibernate Caching verwenden

Prost

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top