2010-09-14 29 views
3

J'ai une table de catégorie avec:table d'auto-référentiel et la fonction SQL récursif

  • categoryID
  • parentCategoryID
  • categoryName

et une table articles avec:

  • numéro d'article
  • categoryID
  • ITEMNAME

J'utilise MySQL. Je veux écrire une requête qui retournera un nombre d'éléments dans une catégorie donnée un categoryID. La requête doit renvoyer le nombre total de tous les éléments dans toutes les sous-catégories de la catégorie donnée.

J'espère que cela a du sens .. désolé si je n'utilise pas la bonne nomenclature.

+0

Y a-t-il un certain nombre de sous-catégories dans chaque catégorie, peut-être? – Fanis

+0

duplication possible de [Requête MySQL récursive?] (Http://stackoverflow.com/questions/3704130/recursive-mysql-query) –

+0

max de 2 niveaux .. donc les catégories parentes principales ont des sous-catégories .. mais ces catégories actuellement n'a pas de sous-catégories. – rodrick

Répondre

2

À quel point êtes-vous coincé sur ce schéma? C'est ce qu'on appelle une «liste d'adjacence», et c'est assez simple, conceptuellement, mais il y a de vraies lacunes. Le plus important d'entre eux est l'incapacité à interroger tous les descendants.

Jetez un oeil à cela, et déterminer si une méthode alternative d'arbres représentant pourrait fonctionner mieux pour vous:

http://pugs.postgresql.org/files/ModelingTrees.pdf

+0

Le lien est rompu. –

0

si, comme vous dites qu'il n'y a que deux niveaux de catégories, puis une simple requête join/alias fonctionnera très bien. Si vous autorisez des profondeurs arbitraires, alors vous devrez aller avec les requêtes récursives fantaisistes ou les ensembles d'adjancency et autres joyeusetés.

En supposant que vous autorisez uniquement les articles à être attaché à la catégorie « inférieure », alors quelque chose comme vous devriez les résultats dont vous avez besoin:

SELECT top.categoryID, top.categoryName, bottom.categoryID, bottom.categoryName, 
    COUNT (items.itemID) 
FROM categories AS top 
LEFT JOIN categories AS bottom ON top.categoryID = bottom.parentCategoryID 
LEFT JOIN items ON bottom.categoryID = items.categoryID 
WHERE (bottom.categoryID = $your_category) 
GROUP BY top.categoryID, bottom.categoryID 

Si vous avez besoin de regarder seulement les catégories de haut niveau, puis modifiez la clause WHERE selon le cas.

+1

ok je pense que cela fonctionnera bien .. mais je me trompais il y a trois niveaux .. cette requête peut-elle être modifiée pour gérer trois niveaux possibles? – rodrick

0

Si vous envisagez les approches décrites par le document référencé par Jeff Dege, à votre contiguïté actuelle liste structure arborescente:

Nested Sets sont très rapides pour les données qui sont lues souvent mais change rarement (lit utilisation SQL BETWEEN et les index, les changements peuvent être coûteux car ils pourraient avoir à mettre à jour plusieurs enregistrements existants), tandis que Énumération de chemin (également connu sous le nom Materialized Path) fournit des performances de lecture acceptables pour les index et LIKE '[path]%' requêtes (au moins pour MySQL comme autant que je sache) et une bonne performance pour les opérations d'insertion et des performances acceptables lors du déplacement d'une catégorie vers une catégorie différente.

Personnellement, j'ai un projet où j'utilise l'énumération de chemin avec des ID de base de données en tant qu'éléments de chemin et un point . pour séparer les éléments (par exemple le chemin d'ancêtre 1.2.3.).

Vous voudrez peut-être effectuer vos propres benchmarks pour comparer ces approches, en particulier si vous avez beaucoup de catégories (plusieurs milliers ou plus).