requête dans une seule table

Mammouth du PHP | 514 Messages

30 oct. 2006, 16:26

Bonjour,

j'ai une table qui a pour champs :

id, nom, parentId (ça suffira pour ce que je veux). Elle liste des utilisateurs. Elle est liée à elle même. quelques données :

id nom parentId
1 mathieu 3
2 frank 3
3 invités 0
4administrateurs 0
5 jean 4

Bref, je voudrais pouvoir ressortir tous les résultats avec les liens entre les objets parents et enfants.

Ca peut se faire ?
Ne jamais repousser à demain ce qu'on peut faire après demain ...

Mammouth du PHP | 19672 Messages

30 oct. 2006, 16:51

Il faut faire une auto-jointure, donc virtuellement créer une copie de la table pour la joindre avec son original :

Il y a toutefois un problème avec ton jeu d'essai :

Code : Tout sélectionner

+----+-----------------+----------+ | id | nom | parentId | +----+-----------------+----------+ | 1 | mathieu | 3 | | 2 | frank | 3 | | 3 | invités | 0 | | 4 | administrateurs | 0 | | 5 | jean | 4 | +----+-----------------+----------+
Comment as-tu pu déterminer la valeur de l'identifiant parent des lignes 1 et 2 puisque l'identifiant "3" n'existait pas ? :-k

Je propose de partir du même jeu revu et corrigé suivant :

Code : Tout sélectionner

+----+-----------------+----------+ | id | nom | parentId | +----+-----------------+----------+ | 1 | administrateurs | 0 | | 2 | invités | 0 | | 3 | mathieu | 2 | | 4 | frank | 2 | | 5 | jean | 1 | +----+-----------------+----------+
Nous devons alors obtenir en sortie le tableau suivant :

Code : Tout sélectionner

+-----------------+---------+ | parent | enfant | +-----------------+---------+ | administrateurs | jean | | invités | mathieu | | invités | frank | +-----------------+---------+
Peux-tu confirmer que c'est bien ce que tu veux obtenir ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Mammouth du PHP | 514 Messages

30 oct. 2006, 16:53

vouiiiiiiiiiiiiiiiii


mais comment ?

en fait, quand je crée un utilisateur, je crée une ligne vide. C'est pour ça qu'un utilisateur peut être créé avant un groupe, et y être associé plus tard.

Ca m'évite de faire des contrôles de partout, de gérer des insert et des update à foison. Je gère uniquement les update, en fait.
Ne jamais repousser à demain ce qu'on peut faire après demain ...

Mammouth du PHP | 19672 Messages

30 oct. 2006, 17:09

Alors deux options, la première :

Code : Tout sélectionner

mysql> SELECT i1.`nom` AS Parents, i2.`nom` AS enfants -> FROM `inscrits` AS i1, `inscrits` AS i2 -> WHERE i1.`id` = i2.`parentId` -> AND i2.`id` <> 0 -> ORDER BY i1.`id`; +----------------+---------+ | Parents | enfants | +----------------+---------+ | Administrateur | Jean | | Invites | Franck | | Invites | Mathieu | +----------------+---------+ 3 rows in set (0.01 sec)
La seconde possibilité va sortir tout même si un parent n'a pas d'enfants :

Code : Tout sélectionner

mysql> SELECT i1.`nom` AS Parents, i2.`nom` AS enfants -> FROM `inscrits` AS i1 -> LEFT JOIN `inscrits` AS i2 -> ON i1.`id` = i2.`parentId` -> AND i2.`id` <> 0 -> ORDER BY i1.`id`; +----------------+---------+ | Parents | enfants | +----------------+---------+ | Administrateur | Jean | | Invites | Mathieu | | Invites | Franck | | Mathieu | NULL | | Franck | NULL | | Jean | NULL | +----------------+---------+ 6 rows in set (0.02 sec)
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 193 Messages

30 oct. 2006, 17:10

Ca m'évite de faire des contrôles de partout, de gérer des insert et des update à foison. Je gère uniquement les update, en fait.
Et maintenant tu découvres le revers de la médaille? :P

Mammouth du PHP | 514 Messages

30 oct. 2006, 17:14

absolument pas en fait. C'est juste que je suis infoutu de lier des champs dans une même table.

En l'occurence, quand je travaille avec les utilisateurs, ils apprécient avoir la possibilité de cliquer sur un bouton : "nouvel objet", limite de le faire plusieurs fois, et de remplir ensuite les champs de chaque objet.

Il n'y a pas vraiment de revers à la médaille, en fait. Je gagne du temps, mon code est plus léger, plus propre, la base de données est à peine plus solicitée, et je me permets de passer plus de temps sur la sécurité des données envoyées, du coup.

Enfin si tu vois des points négatifs que je devrais souligner, ça m'intéresse, auquel cas je ne suis pas contre revoir ma position. Pour l'instant, et pour avoir essayé les deux méthodes, celle ci m'apparaît nettement plus efficace.

Evidemment, derrière, je gère de quoi supprimer les enregistrements vides (tous ceux qui ont plus de 24 heures, et qui n'ont jamais connu de modification).
Ne jamais repousser à demain ce qu'on peut faire après demain ...

Mammouth du PHP | 19672 Messages

30 oct. 2006, 17:17

Tiens, j'ajoute une version de la première option proposée en utilisant un JOIN :

Code : Tout sélectionner

mysql> SELECT i1.`nom` AS Parents, i2.`nom` AS enfants -> FROM `inscrits` AS i1 -> LEFT JOIN `inscrits` AS i2 -> ON i1.`id` = i2.`parentId` -> WHERE i1.`parentId` = 0 -> ORDER BY i1.`id`; +----------------+---------+ | Parents | enfants | +----------------+---------+ | Administrateur | Jean | | Invites | Mathieu | | Invites | Franck | +----------------+---------+ 3 rows in set (0.00 sec)
Modifié en dernier par Cyrano le 30 oct. 2006, 17:18, modifié 1 fois.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Mammouth du PHP | 514 Messages

30 oct. 2006, 17:18

C'est un génie notre cyrano.

Si t'étais pas un homme, j't'épouserais.

ça m'ferait gagner pas mal de temps en dev' ...
Ne jamais repousser à demain ce qu'on peut faire après demain ...

Mammouth du PHP | 19672 Messages

30 oct. 2006, 17:19

Pas de quoi ;)
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe: