Quel type de structure de base de données dois-je utiliser pour un site comportant une sous-catégorie infinie?

StackOverflow https://stackoverflow.com/questions/1418160

Question

Par exemple, "Dole Banana" est un type de produit, il est répertorié sous le symbole "Bananes". catégorie, lorsque j'ouvre le "Fruits" catégorie "Je veux voir" Dole Banana ".

+ Food
|--+ Fruits
|------+ Bananas   
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
Était-ce utile?

La solution

J'ai généralement utilisé des arborescences gauche-droite , qui sont très bien adaptés aux requêtes de base de données. Vous avez une valeur parentId, left et right pour chaque nœud. Chaque nœud enfant a une valeur gauche / droite située entre les nœuds parents gauche et droite, ce qui facilite la recherche, par exemple, de tous les enfants / parents d'un nœud. Cela donne un léger surcoût sur les insertions, mais cela ne devrait pas avoir trop d'impact à moins d'insérer beaucoup.

Modifier: un simple avertissement cependant, vous devez effectuer les opérations d’insertion / mise à jour dans une transaction verrouillée, sinon l’arborescence peut être gâchée.

Autres conseils

Si vous recherchez des ressources en ligne permettant de résoudre ce problème, " Stockage d'un arbre dans une base de données " serait une bonne phrase de recherche.

En ce qui concerne la solution, notez que chaque sous-catégorie peut avoir une ou deux catégories parentes. Par conséquent, l’arbre entier peut être stocké dans une seule table auto-référencée avec un "parent". champ.

En utilisant votre exemple d'arborescence:

 ID  | PARENT | NAME
-----+--------+-------------
  1  |  null  | Food
  2  |   1    | Fruits
  3  |   2    | Bananas
  4  |   2    | Apples
  5  |   1    | Vegetables
  6  |   5    | Onion
  7  |   5    | Spinach

Une table " Catégories " avec 3 champs.

  1. CategoryId non null (clé primaire)
  2. ParentCategoryId null
  3. Nom de catégorie non nul

Pour obtenir toutes les catégories de racines

select * from Categories where ParentCategoryId is null

Pour obtenir toutes les sous-catégories d'une catégorie spécifique:

select * from Categories where ParentCategoryId = 12

Vous pouvez utiliser une structure de table simple avec parent_category_id et récupérer une arborescence complète avec récursion ou implémenter des valeurs gauche / droite et récupérer une arborescence complète à l'aide de la méthode de parcours de l'arborescence préordonnée.

Si vous voulez dire un nombre infini de niveaux, alors une table d’auto-référencement qui peut être récursive. Exemple: StuffID, StuffName, StuffParentID (FK to Stuff ID)

Pour un nombre fini, tables fixes: parent-enfant-petit-enfant

    CREATE TABLE [dbo].[Category](
    [CategoryId] [int] NOT NULL,
    [ParentCategoryId] [int] NULL,
    [CategoryName] [nvarchar](50) NOT NULL,
     CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED 
    (
        [CategoryId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON 

[PRIMARY]

GO

ALTER TABLE [dbo].[Category]  WITH CHECK ADD  CONSTRAINT [FK_Category_Category] FOREIGN KEY([ParentCategoryId])
REFERENCES [dbo].[Category] ([CategoryId])
GO

ALTER TABLE [dbo].[Category] CHECK CONSTRAINT [FK_Category_Category]
GO

Voici une approche différente qui pourrait vous être utile. Les coûts de maintenance sont légèrement supérieurs à ceux de l’approche PARENT_ID ou lft / rght, mais la récupération est beaucoup plus facile (et plus rapide).

Les bananes Dole peuvent être dans la table des produits. Vous avez un seul category_id pour un produit.

Nous avions l'obligation de permettre plusieurs catégories pour un produit. Cela nous a conduit à avoir une table de jonction categories_products, où le produit pourrait avoir plusieurs lignes jointes. Ensuite, nous devions décider si nous avions des bananes Dole dans les bananes uniquement, ou dans les bananes et tous ses parents. La rapidité de récupération étant cruciale, nous avons classé les bananes dole dans ses catégories et dans toutes leurs catégories parentes. Il existe trois catégories de produits joints pour les bananes dole.

À l'aide de cette structure, le renvoi de tous les éléments de n'importe quelle catégorie est facile et rapide, une seule requête. Vous ne pouvez pas faire cela dans l'approche PARENT_ID (sauf si vous codez en dur les parents, les grands-parents, etc.) L'ajout d'une catégorie est facile. La catégorisation d'un produit nécessite l'insertion de plusieurs lignes dans la table de jointure. La suppression et le déplacement de catégories sont un peu plus compliqués.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top