Page 1 sur 1

Requête de tri récursif...

Posté : 11 nov. 2005, 19:00
par Cyrano
Une fois n'est pas coutume, j'ai une question ;)

Mon problème est le suivant. J'ai une table de catégories reliée à une table de rubriques. J'ai donc pour chaque ligne de la table catégorie une clé étrangère faisant référence à une ligne de la table rubrique. Là où ça se corse un brin, c'est que certaines catégories comportent des sous-catégories.

J'ai bien une série de fonctions PHP pour faire une recherche récursive et me classer tout ça en échelonnant en fonction du niveau de profondeur : ça fonctionne très bien, mais ça ne me satisfait pas du tout pour une raison fort simple: j'ai par exemple 16 lignes dans ma table catégorie et ça me génère donc 16 requêtes. Je dois pouvoir ramener ça à une seule requête. Le but étant de mettre le résultat dans un tableau sur lequel je ferai ensuite les opérations nécessaire pour un affichage selon la nécessité de la page.

Voilà actuellement une base sommaire:

Code : Tout sélectionner

mysql> SELECT rub_id, cat_id, cat_id_parent, cat_libelle -> FROM categorie; +--------+--------+---------------+-----------------------------+ | rub_id | cat_id | cat_id_parent | cat_libelle | +--------+--------+---------------+-----------------------------+ | 4 | 1 | 0 | Véhicules Peugeot | | 4 | 2 | 0 | Véhicules Renault | | 4 | 3 | 1 | Berlines | | 4 | 4 | 1 | Les coupés | | 4 | 5 | 1 | Les utilitaires | | 4 | 6 | 5 | Les fourgons fermés Peugeot | | 1 | 7 | 0 | Les Appartements | | 1 | 8 | 0 | Maisons | | 1 | 9 | 8 | Maisons de campagne | | 1 | 10 | 8 | Les maisons urbaines | | 1 | 11 | 0 | Les vacances | | 4 | 12 | 1 | Les deux roues | | 3 | 13 | 0 | La cuisine | | 3 | 14 | 0 | Le salon | | 3 | 15 | 0 | Les chambres | | 3 | 16 | 0 | La salle à manger | +--------+--------+---------------+-----------------------------+
Sans aucun tri, ça ne va pas me faciliter la vie. J'ai donc ajouté des clauses de tri :

Code : Tout sélectionner

mysql> SELECT rub_id, cat_id, cat_id_parent, cat_libelle -> FROM categorie -> ORDER BY rub_id, cat_id_parent, cat_id; +--------+--------+---------------+-----------------------------+ | rub_id | cat_id | cat_id_parent | cat_libelle | +--------+--------+---------------+-----------------------------+ | 1 | 7 | 0 | Les Appartements | | 1 | 8 | 0 | Maisons | | 1 | 11 | 0 | Les vacances | | 1 | 9 | 8 | Maisons de campagne | | 1 | 10 | 8 | Les maisons urbaines | | 3 | 13 | 0 | La cuisine | | 3 | 14 | 0 | Le salon | | 3 | 15 | 0 | Les chambres | | 3 | 16 | 0 | La salle à manger | | 4 | 1 | 0 | Véhicules Peugeot | | 4 | 2 | 0 | Véhicules Renault | | 4 | 3 | 1 | Berlines | | 4 | 4 | 1 | Les coupés | | 4 | 5 | 1 | Les utilitaires | | 4 | 12 | 1 | Les deux roues | | 4 | 6 | 5 | Les fourgons fermés Peugeot | +--------+--------+---------------+-----------------------------+
C'est mieux, mais pas encore ça : j'essaye de trouver une manière de formuler ma requête pour obtenir ceci:

Code : Tout sélectionner

+--------+--------+---------------+-----------------------------+ | rub_id | cat_id | cat_id_parent | cat_libelle | +--------+--------+---------------+-----------------------------+ | 1 | 7 | 0 | Les Appartements | | 1 | 8 | 0 | Maisons | | 1 | 9 | 8 | Maisons de campagne | | 1 | 10 | 8 | Les maisons urbaines | | 1 | 11 | 0 | Les vacances | | 3 | 13 | 0 | La cuisine | | 3 | 14 | 0 | Le salon | | 3 | 15 | 0 | Les chambres | | 3 | 16 | 0 | La salle à manger | | 4 | 1 | 0 | Véhicules Peugeot | | 4 | 3 | 1 | Berlines | | 4 | 4 | 1 | Les coupés | | 4 | 5 | 1 | Les utilitaires | | 4 | 6 | 5 | Les fourgons fermés Peugeot | | 4 | 12 | 1 | Les deux roues | | 4 | 2 | 0 | Véhicules Renault | +--------+--------+---------------+-----------------------------+
Pour visualiser mieux de quoi il est question, je pourrais par exemple ensuite afficher ceci:
- Logement -
Les Appartements
Maisons
->Maisons de campagne
->Les maisons urbaines
Les vacances
- Mobilier -
La cuisine
Le salon
Les chambres
La salle à manger
- Véhicules -
Véhicules Peugeot
->Berlines
->Les coupés
->Les utilitaires
->->Les fourgons fermés Peugeot
->Les deux roues
Véhicules Renault

Posté : 11 nov. 2005, 22:39
par Cyrano
Bon, je laisse le sujet, mais vous tracassez pas trop, je passerai pas ma vie là-dessus. Si vous avez une solution, je reste preneur, mais compte tenu de la version de MySQL utilisée, je n'ai pas la possibilité d'utiliser de procédure stockée. En outre, j'ai beau tourner le problème dans tous les sens, à l'endroit comme à l'envers, je ne suis même pas sûr que ce soit possible, donc la solution va passer par un tri récursif sur le tableau des données récupérées avec une requête simple.

Merci à ceux qui auront quand même passé du temps à réfléchir à la question :)

Posté : 12 nov. 2005, 02:19
par ouckileou
Salut,

désolé je ne vais pas solutionner ton problème mais il y a une méthode qui permet justement de ne pas s'embêter avec ces requêtes récursives et compliquées : Gestion d'arbres par représentation intervallaire

(elle a déjà été postée sur le forum mais cela s'applique bien)

Sinon j'ai beau chercher je ne vois pas trop comment tu pourrais faire en une seule requête... une procédure stockée est envisageable ?

Posté : 12 nov. 2005, 03:17
par fab
tu pourrais stocker dans des arrays et faire le tri en php en suivant c'est la méthode que je vois :s

Posté : 12 nov. 2005, 07:33
par Cyrano
une procédure stockée est envisageable ?
Malheureusement non, justement. Les procédures stockées ne sont disponibles qu'à partir de MySQL 5 et c'est pour mon espace 1&1, donc je ne dispose que de la version 4.0. Il y aurait la solution de monter la base avec SQLite en PHP5 qui me donnerait accès aux procédures stockées, mais je prévois que la base risque à terme d'atteindre un volume non négligeable et je reste circonspect quant à l'efficacité à long terme avec cette base avec des grandes quantités d'informations...
tu pourrais stocker dans des arrays et faire le tri en php en suivant c'est la méthode que je vois
Même chose pour moi, c'est la seule solution raisonnablement efficace que j'ai trouvée.

En fait le problème est simple : sur la base des colonnes dont je dispose, je n'ai pas d'élément me permettant de faire un classement de la manière dont je le voudrais, à savoir une catégorie immédiatement suivie de ses sous-catégories avant de passer à la catégorie suivante.

Alors j'ai bien sûr le contrôle de ma base et je pourrais la modifier à mon gré, mais je ne vois pas non plus comment je pourrais ajouter une colonne me permettant d'obtenir le classement souhaité.

Enfin merci quand même, je vais me rabattre sur un tri récursif de tableaux indexés et je sens que je vais passer des instants de fièvre cérébrale intéressants :langue:

[Edit]Bon, j'y suis arrivé, pour moitié en SQL et pour l'autre moitié avec deux fonctions de tri récursif sur un tableau. Je ne mets pas la solution ici, ça n'expliquerait pas grand chose, j'y ai quand même passé plus de deux jour, je ne peux pas résumer et quelques lignes. Il faudrait un cours intensif pendant une grosse heure pour décortiquer tout ça.

Je mets en délestage à cause de ça : pas de solution affichée. Et résolu quand même.[/Edit]