IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Requête SQL pour charger une structure récursive


Sujet :

PHP & Base de données

  1. #1
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut Requête SQL pour charger une structure récursive
    Bonjour à tous !

    Avant de commencer, j'ai fait plusieurs recherches, et il existe beaucoup de sujets semblable, mais je n'ai rien trouvé d'assez précis.

    J'ai donc un menu du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    - zone 1
    -- section 1
    -- section 2
    - zone 2
    -- section 3
    --- catégorie 1
    --- catégorie 2
    -- section 4
    etc...

    Pour ce menu, je ne ne connais pas le nombre de profondeur de niveaux. Il peut y en avoir une infinité. La seule chose dont je suis sur, c'est qu'il n'y a pas de boucle dans les références.

    Pour ce menu, j'ai une table MySQL dont la structure (pour l'exemple) est très simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    - id
    - parentId
    - nom
    ce qui donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    1, 0, "zone 1"
    2, 1, "section 1"
    3, 1, "section 2"
    4, 0,  "zone 2"
    5, 4, "section 3"
    6, 5, "catégorie 1"
    7, 5, "catégorie 2"
    8, 4, "section 4"

    Actuellement, tout les résultats sont en ordre. Les zone toujours avant les section, et les section toujours avant les catégories.

    Mais considérons que ce soit le "bordel" ( j'ai changé les id, mais la hyérarchie n'à pas changée. Le menu devrait être identique ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    1, 3, "section 1"
    2, 3, "section 2"
    3, 0, "zone 1"
    4, 7, "catégorie 1"
    5, 7, "catégorie 2"
    6, 0,  "zone 2"
    7, 6, "section 3"
    8, 6, "section 4"

    Je cherche à effectuer une (1) requête afin de récupérer l'ensemble des données et de pouvoir constituer soit un array multi-dimensionnel, soit un objets qui se contiens lui-même récursivement (pattern composite je crois)

    Actuellement, si je charge les données, j'aurais un problème:
    Lorsque je voudrais associer la catégorie 1 (id #4), je ne pourrais pas, car l'item section 3 (id #7) n'existe pas encore...

    donc logiquement, je me dis que je devrais faire une fonction récursive, telle que:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    function loadMenu($parentId)
    {
        //Trouver et charger tous les éléments parentId = $parentId
        ....
        $arr[] = mysql_fetch_assoc(....); 
     
        foreach($arr as $key=>$elem)
            $arr[$key]['sub'] = loadMenu($elem['parentId']); //Charger tous les éléments enfants
     
        return $arr;
    }
     
    $arr = loadMenu(0);
    var_dump($arr);
    ... sauf que cette méthode implique de faire une requête de facon récursive, et je ne veux pas faire celà.



    Ma question est donc: En une seule requête, comment puis-je, extraire mes résultats efficacement dans ce cas de figure ?




    Question connexe:
    En terme de performance, puis-je me permettre de faire des exécution de requête de facon récursive si j'utilise PDO avec une requête préparée ?

  2. #2
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 395
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 395
    Points : 15 757
    Points
    15 757
    Par défaut
    Citation Envoyé par FMaz Voir le message
    Ma question est donc: En une seule requête, comment puis-je, extraire mes résultats efficacement dans ce cas de figure ?
    il y a une solution dans ce cas mais elle impose de modifier complètement la structure de la table

    la structure est expliqué ici :
    http://sqlpro.developpez.com/cours/arborescence/

    cette structure rends les modifications plus compliquées mais ensuite la lecture de l'arborescence est beaucoup plus rapide

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    625
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 625
    Points : 822
    Points
    822
    Par défaut
    A priori un simple ORDER BY parentId devrait t'éviter les mauvaises surprises pour la "remise en ordre" du bordel possible dans ta table.

    Ensuite le classement via objets est simple à mettre en oeuvre et me parait la meilleure solution.

    Bon courage

  4. #4
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Oulà ! c'est du costaud comme théorie ... j'ai commencé à l'éplucher rapidement, et c'est déjà extrêmement intéressant, mais je vais devoir approfondir plus que ça !


    #1:
    Ceci étant dit, la moindre modification demande de ré-indexer (replacer les bornes) sur tout les éléments subséquents n'est-ce pas ?


    #2:
    Logiquement, si un système ne permet pas de créer de sous-catégorie avant la catégorie parent, et qu'il ne peut pas y avoir de branches orpheline (sans parent), un order by sur valeur en auto-incrément assure que la catégorie parent sera toujours chargée avant ses enfants.

    (Ce qui était hors de ma demande initiale, je sais)


    #3
    Concernant les requêtes PDO préparés (pdo->prepare()), le gain de performance est-il intéressant au point de permettre de faire des exécutions de requête dans des boucles (pour poser un chiffre, disons de 100)





    Quoi qu'il en soit, merci énormément pour cette documentation !

  5. #5
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Pas idiot pour le orderby sur la clé parentId... Cependant, ca ne permet pas d'obtenir une branche du menu sans faire appel à la récursivité.



    Exemple, si je désire avoir uniquement le listing de la zone2:
    - section3
    -- cat 1
    -- cat 2
    - section 4

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    1, 0, "zone 1"
    2, 1, "section 1"
    3, 1, "section 2"
    4, 0,  "zone 2"
    5, 4, "section 3"
    6, 5, "catégorie 1"
    7, 5, "catégorie 2"
    8, 4, "section 4"
    9, 0, "zone 3"
    ... je vois mal comment une seule requête pourra y arriver avec la méthode d'auto-jointure.

Discussions similaires

  1. Requête SQL pour récupérer la structure d'une table
    Par Emyleen dans le forum Développement
    Réponses: 2
    Dernier message: 10/09/2012, 16h57
  2. Réponses: 2
    Dernier message: 23/10/2009, 10h29
  3. Requête sql pour afficher une somme
    Par nora2311 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 12/06/2009, 16h47
  4. Requête SQL pour remplir une zone de texte déroulante
    Par uranium-design dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 17/10/2007, 12h15
  5. Requête SQL pour insérer une donnée BINAIRE ?
    Par Najdar dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 22/05/2006, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo