Domanda

Ho alcuni prodotti che appartiene a qualche categoria.

Ogni categoria può avere diverse proprietà.

Per esempio,

  • categoria auto ha proprietà colore, potenza, ...
  • categoria animali domestici hanno proprietà peso, età, ...

Numero di categorie è di circa 10-15.Il numero di immobili di ogni categoria è 3-15.Numero di prodotti è molto grande.

Requisito principale di questa app è molto buona ricerca.Possiamo selezionare una categoria e inserire i criteri per ogni struttura di questa categoria.

Sono per la progettazione di database per questo scenario.(SQL Server 2005)

È stato utile?

Soluzione

L'approccio di design classico sarebbe (la stella indica la colonna chiave primaria):

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

Se puoi convivere con il fatto che ogni valore di proprietà andrà al DB come una stringa e tipo di informazioni di conversione sono memorizzate nella tabella Proprietà, questo layout sarebbe sufficiente.

La query dovrebbe andare in questo modo:

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

Più condizioni WHERE vengono fornite (congiuntamente, ad es. utilizzando AND), più veloce sarà la query. Se hai indicizzato correttamente le tue tabelle, cioè.

Allo stato attuale, la soluzione non è ideale per una situazione di indicizzazione del testo completo. Una tabella aggiuntiva che memorizza tutto il testo associato a un ProductId in un modo più denormalizzato potrebbe aiutare qui. Questa tabella dovrebbe essere aggiornata tramite i trigger che sono in attesa di modifiche nella tabella ProductProperty.

Altri suggerimenti

Se l'utente dell'applicazione deve selezionare una categoria prima di poter effettuare una ricerca, separerei i prodotti in tabelle di database diverse per categoria. Questa soluzione è anche indicata dal fatto che le categorie stesse hanno così poco in comune. La suddivisione per categoria renderà inoltre ogni ricerca molto più veloce, poiché il tempo non sarà sprecato nella ricerca di auto quando l'utente cerca un animale domestico.

Dopo aver suddiviso i prodotti in categorie, dovrebbe essere facile creare le tabelle utilizzando le proprietà comuni dei prodotti in ciascuna categoria. L'interfaccia utente dell'applicazione dovrebbe essere dinamica (sto pensando a un modulo Web), in quanto le proprietà tra cui l'utente può scegliere dovrebbero cambiare quando l'utente seleziona una categoria.

Nota: se hai prodotti che desideri siano elencati in più categorie, questa soluzione genererà dati duplicati nelle tue tabelle. C'è un compromesso tra velocità e normalizzazione durante la progettazione di un database. Se non hai prodotti che rientrano in più categorie, penso che questa sarà la soluzione più veloce (in termini di velocità di ricerca).

La maggior parte delle persone consiglia di utilizzare varianti del progetto Entity-Attribute-Value (EAV). Questo design è eccessivo per la tua situazione e introduce un sacco di problemi, ad esempio:

  • Non è possibile definire il tipo di dati per un attributo; puoi inserire " banana " per un attributo intero
  • Non è possibile dichiarare obbligatorio un attributo (ovvero NON NULL in una tabella convenzionale)
  • Non puoi dichiarare un vincolo di chiave esterna su un attributo

Se hai un numero limitato di categorie, è meglio usare la soluzione A nella risposta di Bogdan Maxim. Ossia, definire una tabella Prodotti con attributi comuni a tutte le categorie e una tabella aggiuntiva per ogni categoria, per memorizzare gli attributi specifici della categoria.

Solo se hai un numero infinito di categorie o se devi potenzialmente supportare un diverso set di attributi per riga in Prodotti, EAV è una buona soluzione. Ma poi non stai usando affatto un database relazionale, poiché EAV viola diverse regole di normalizzazione.

Se hai davvero bisogno di tanta flessibilità, sarebbe meglio archiviare i tuoi dati in XML. In effetti, potresti esaminare RDF e framework web semantici come Sesame .

Potresti prendere in considerazione un Entity-Attribute-Value di disposizione, dove puoi " tag " ogni prodotto con coppie arbitrarie di nome / valore.

Puoi provare questo. Non sono troppo sicuro dei dettagli reali della tua domanda, forse qualcuno può aiutarti a tradurre un po 'meglio.

5 tabelle. 3 per la memorizzazione dei dati, 2 per la memorizzazione dei mapping tra i dati.

tProduct 
  productID
  <other product details>

tCategory
  categoryID
  <other category details>

tProperty
  propertyID
  <other property details>

tProductXCategory
  productyID
  categoryID

tCategoryXProperty
  categoryID
  propertyID

Le tue query dovranno unire i dati utilizzando le tabelle di mappatura, ma ciò ti consentirà di avere diverse relazioni diverse tra categoria, proprietà e prodotti.

Utilizza le procedure memorizzate o le query con parametri per ottenere prestazioni migliori dalle tue ricerche.

Se vuoi essere flessibile su categorie e proprietà, devi creare le seguenti tabelle:

  • prodotto: ProductID
  • categoria: ID categoria, ID prodotto
  • proprietà: PropertyID, CategoryID

quando si desidera condividere una categoria su più di un prodotto, è necessario creare una tabella di collegamenti per l'unione n: m:

  • productCategoryPointer: ProdCatID, ProductID, CategoryID.

Dovrai aggiungere alcuni join alle tue query, ma con gli indici giusti, sarai in grado di interrogare rapidamente i tuoi dati.

Si potrebbe provare qualcosa di più orientato.

1.Definire una tabella di base per i Prodotti

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

2.Definire una tabella Categorie

Categories(CategoryID, Name, Description, ..)

Da qui si hanno un sacco di opzioni e quasi tutti di loro di rompere la normalizzazione del database.

Soluzione A.

Sarà un aggiornamento incubo, se è necessario aggiungere nuovi prodotti

A1.Definire una tabella separata per ciascuna delle categorie

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

A2.Join le tabelle in base alle relazioni in modo da poter utilizzare i dati

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

Soluzione B.

Manutenzione incubo per diverse tipologie di immobili (es.int varchar, ecc)

B1.Definire una tabella di Proprietà

CategoryProperty (CPID, Name, Type)

B2.Definire una tabella per contenere le associazioni tra le Categorie e le Proprietà

PropertyAssociation (CPID, PropertyID)

B12.Definire una tabella per mantenere le proprietà (in Alternativa per B1 e B2)

Properties(CategoryID, PropertyID, Name, Type)

B3.Per ogni tipo di struttura (int, double, varchar, etc.) aggiungere una tabella dei valori

PropertyValueInt(ProductID, CPID, PropertyID, Value) - per int PropertyValueString(ProductID, CPID, PropertyID, Value) - per le stringhe PropertyValueMoney(ProductID, CPID, PropertyID, Value) - per i soldi

B4.Unire tutte le tabelle per recuperare la proprietà desiderata.

Utilizzando questo approccio, non dovrà gestire tutte le proprietà in una tabella separata, ma il valore tipi di loro.Fondamentalmente tutte le tabelle coinvolte saranno le tabelle di ricerca.Lo svantaggio è che, al fine di recuperare ogni valore, è necessario "Caso" per ogni tipo di valore.

Prendere in considerazione questi articoliqui e qui) quando la scelta di uno di questi approcci. Questo post del forum è anche interessante e in qualche modo legati al tema, anche se è la localizzazione.

Si potrebbe anche usare Tomalak risposta e aggiungere la tipizzazione forte se si sente il bisogno.

Di recente ho dovuto farlo e sto usando NHibernate dove ho tre entità

Categoria opzione prodotto categoria opzione

Un prodotto ha 1 * Categorie

Un prodotto ha 1 * Opzione

Un'opzione ha 1 OptionCategory

una volta impostato, è possibile utilizzare la cache di divieto

Saluti

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top