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

Requêtes MySQL Discussion :

[Select Join] Plusieurs lignes possibles dans la table jointe.


Sujet :

Requêtes MySQL

  1. #1
    Membre à l'essai
    Inscrit en
    Mai 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 19
    Points : 13
    Points
    13
    Par défaut [Select Join] Plusieurs lignes possibles dans la table jointe.
    Bonjour,

    J'ai un problème qui fera sans doute sourire les vieux routards, et qui est ridicule au point que je suis persuadé avoir *su* la réponse. Mais là je suis un peu dans le brouillard.


    J'ai deux tables :

    La première comprend les données principales pour chaque enregistrement, par exemple Numéro, rue, ville, etc., ainsi qu'un identifiant ID.

    La seconde table contient une liste de personnes : Nom, prénom, etc., Chaque "personne" possède également un identifiant ID, indentique à celui de la maison où il habite.

    Chaque ligne de la première table peut donc correspondre à plusieurs lignes de la seconde, car comme vousl'aurez compris plusieurs personnes peuvent vivre à la même adresse.


    Je fais donc la jointure comme ça :

    SELECT DISTINCT table1.ID,table1.numero ,table1.rue,table2.nom,table2.prenom FROM table1 LEFT JOIN table2 ON table2.ID=table1.ID WHERE (table1.rue like '%X%' or table2.nom like '%X%' ) ORDER BY table2.nom,table1.rue

    Mon problème : Si plusieurs enregistrements de la table 2 correspondent à la recherche, il va me sortir une ligne pour chaque. C'est logique, mais ce n'est pas ce que je veux.
    Ainsi, si le champs de recherche concerne Durand et qu'il y a deux Durand, à la même adresse, il va me sortir :

    Ligne 1 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom]=Durand ; [prenom]=David
    Ligne 2 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom]=Durand ; [prenom]=Laurent


    Or moi, j'aimerai mieux avoir quelque chose du genre :

    Ligne 1 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom1]=Durand ; [nom2]=Durand ; [prenom][1]=David ; [prenom][2]=Laurent



    Est-ce-possible ?

    Si oui, comment faire ?

    Sinon, comment résolvez-vous ce problème quand il se présente à vous ?

  2. #2
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Bonjour,

    C'est théoriquement possible mais pas du tout souhaitable car un SGBD n'est pas là pour faire ce genre de présentation cosmétique.

    C'est dans le code de l'application cliente qu'on organise les données du jeu de résultats pour les présenter de telle ou telle manière.
    Pensez au bouton

  3. #3
    Membre à l'essai
    Inscrit en
    Mai 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 19
    Points : 13
    Points
    13
    Par défaut
    Quelle cosmétique ?

    Je veux simplement que le Select me renvoit l'ensemble des lignes de la table2 correspondant à chaque ligne trouvée dans la table 1 ?

    Ou est la cosmétique là dedans ? J'ai été voir le lien donné, mais je ne vois pas réellement le rapport (il est vrai que l'exemple qui y est donné est, je dirais, sciemment monstrueux).

  4. #4
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    L'exemple le plus classique est le suivant... Je voudrais que mes données en colonnes soient remise en ligne et tout cela dans une jolie requête !
    Ben voyons...
    [...]
    Tu n'as pas l'impression que la requête que tu veux faire s'inscrit exactement dans cette logique ?

    Encore une fois c'est sûrement techniquement faisable (comme le concède Sqlpro dans son article) mais le prix en complexité de construction de la requête et en performances est atrocement lourd.
    Pensez au bouton

  5. #5
    Membre à l'essai
    Inscrit en
    Mai 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 19
    Points : 13
    Points
    13
    Par défaut
    Ah. Je n'avais pas compris le sens de la phrase.


    Dans ce cas, je ne vois pas trop comme faire. Les exemple donnés sont réellement trop complexes... pour moi : C'est plus une étude de cas complexe et particulière, à destination de gens pour qui le problème ne se pose que par distraction ou ignorance de ce point précis (trop de choses sans aucun rapport avec la question posée : Extractions de parties de dates, 12 références alors que deux auraient suffit, périodes temporelles, sommes, valeurs 0 placées dans des valeurs de sortie...). Vous me direz que c'est un défaut de beaucoup de didacticiels sur Internet : Conçus pour ceux ayant un niveau équivalent à celui qui écrit.

    Bref...

    Je vais quand-même essayer de comprendre, et si je n'y arrive pas je reviendrais gratter à la porte...

  6. #6
    Membre à l'essai
    Inscrit en
    Mai 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 19
    Points : 13
    Points
    13
    Par défaut
    Bon.

    Alors voila où j'en suis.


    Faire ce que j'avais pensé est à oublier (mais sqlpro n'est définitivement pas un site pour non-pro : Tous les exemples sont directement des études de cas. Ça me paume complètement ).


    J'envisage donc de faire deux requêtes à la suite :

    La première prendra les enregistrements de la table principale, comme ça :

    SELECT DISTINCT table1.ID,table1.numero ,table1.rue,FROM table1 LEFT JOIN table2 ON table2.ID=table1.ID WHERE (table1.rue like '%X%' or table2.nom like '%X%' ) ORDER BY table2.nom,table1.rue
    La seconde prendra les enregistrement de la ou des tables secondaires, comme ça :

    SELECT DISTINCT table2.ID,table2.nom,table2.prenom FROM table1 LEFT JOIN table2 ON table2.ID=table1.ID WHERE (table1.rue like '%X%' or table2.nom like '%X%' ) ORDER BY table2.nom,table1.rue
    Deux requêtes pour éviter de requérir inutilement plusieurs fois les éléments de Table1 pour les cas où il y aurait plusieurs lignes de Table2 s'y rapportant.



    Ensuite, je fais un truc comme ça (en PHP) :


    boucle while (sur chaque ligne de résultat de Requete1)
    {

    Pour chaque élément désiré par le code :

    - soit prise directement de l'élément en question ;

    - soit boucle while(sur chaque ligne de résultat de Requete2)
    {
    Si table1.ID = table2.ID alors traitement de l'élément.
    }

    }



    Le problème est qu'il y aura probablement plusieurs tables secondaires (table2, mais aussi table3, table4, etc.). Ce qui signifie donc une requête de plus par table supplémentaire...

    Je continue mes recherches.

  7. #7
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Je ne comprends pas pourquoi tu te compliques autant la vie

    Avec ce genre de jeu de résultats

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Ligne 1 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom]=Durand ; [prenom]=David
    Ligne 2 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom]=Durand ; [prenom]=Laurent
    ...
    Tu as bien toutes les données voulues, non ?
    Et ce en une seule requête relativement simple. C'est le principe des jointures...
    Pensez au bouton

  8. #8
    Membre à l'essai
    Inscrit en
    Mai 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 19
    Points : 13
    Points
    13
    Par défaut
    J'ai tout lu sacher-masoch.



    Oui, certes, j'ai toutes les données voulues, mais deux problèmes se posent :


    1°La table1 peut comporter une quinzaine de données, la plupart demandées par la requête. La table 2 peut comporter de 0 à X lignes correspondant à l'égalité table1.ID=table2.ID (non, le script ne connaît pas la valeur de X, et X peut changer pour chaque occurence - Une maison peut avoir 0 à X habitants).
    Donc si par exemple il y a 7 habitants dans la maison, cela va faire demander 7 fois les mêmes renseignements sur la maison (qui peuvent être longs : Imagine l'historique de la maison ou la liste des plantes du jardin)...
    Je ne sais pas si cela va prendre des ressources supplémentaires a MySQL, mais cela va en prendre au serveur lorsque PHP va lire, mettre en mémoire et parser tout ça.

    Surtout si une table3 similaire à table2 s'en mêle (elle pourraît par exemple lister les transports voisins et leur distance à la maison).
    S'il y a, disons, trois transports voisins (deux bus et l'autoroute), est-ce-que nous ne risquons pas d'avoir 3*2=6 lignes renvoyées par MySQL pour le même sujet.
    Et avec 7 habitants et 13 transports (Deux métros, trois avenues principales voisines, RER, SNCF et 6 ligne de bus) on a 91 lignes renvoyées...
    Et ça juste pour des maisons.

    C'est juste que j'ai du mal à me faire à l'idée d'un gaspillage pareil.





    2° Il faut parser les résultats. Donc les mettre dans un tableau, alors que pour le moment le script se contente d'un "while(mysql_fetch_row/array)", ce qui est tout de même très largement moins coûteux.

    Il faut également que la première clause Order soit obligatoirement "ID" pour être certain que toutes les lignes concernant la même maison (table1) restent ensemble (le script peut demander les détails de plusieurs maisons). Je peux me tromper, mais n'est-ce-pas rajouter un traitement supplémentaire lourd à la requête ?

  9. #9
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par vampiloup
    1°La table1 peut comporter une quinzaine de données, la plupart demandées par la requête. La table 2 peut comporter de 0 à X lignes correspondant à l'égalité table1.ID=table2.ID (non, le script ne connaît pas la valeur de X, et X peut changer pour chaque occurence - Une maison peut avoir 0 à X habitants).
    Donc si par exemple il y a 7 habitants dans la maison, cela va faire demander 7 fois les mêmes renseignements sur la maison (qui peuvent être longs : Imagine l'historique de la maison ou la liste des plantes du jardin)...
    OK mais là tu modifies les données du problème qui au départ étaient simplement de nous sortir l'id de la personne, son nom, l'id du domicile et la rue.
    Je pensais que tu voulais afficher les résultats d'une recherche, donc juste quelques lignes sur lesquelles on clique pour avoir le détail de l'objet en question.

    Si sur la même page Web tu comptes afficher pour chaque maison le nombre de barreaux du portail, l'âge de la grand-mère de l'architecte et le temps moyen pour se rendre à la gare la plus proche en patins à roulettes c'est carrément autre chose. Là je suis bien d'accord qu'il vaut mieux faire plusieurs requêtes.


    Citation Envoyé par vampiloup
    2° Il faut parser les résultats. Donc les mettre dans un tableau, alors que pour le moment le script se contente d'un "while(mysql_fetch_row/array)", ce qui est tout de même très largement moins coûteux.
    J'ai du mal à saisir... Les résultats sont déjà dans un tableau, on peut parfaitement les parser tels quels !

    Citation Envoyé par vampiloup
    Il faut également que la première clause Order soit obligatoirement "ID" pour être certain que toutes les lignes concernant la même maison (table1) restent ensemble (le script peut demander les détails de plusieurs maisons). Je peux me tromper, mais n'est-ce-pas rajouter un traitement supplémentaire lourd à la requête ?
    Pas nécessairement, surtout s'il y a peu de maisons.
    Pensez au bouton

  10. #10
    Membre à l'essai
    Inscrit en
    Mai 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 19
    Points : 13
    Points
    13
    Par défaut
    Je n'ai pas été assez clair, désolé : Je m'intéresse au principe, à la manière de le faire avec n'importe quelles données.

    Je vais essayer de faire le plus simplement possible :

    J'ai deux tables. Chaque ligne de la première table correspond à X lignes de la seconde table. Les deux tables correspondent par un champs ID, identique dans les deux tables.

    Mon but est que lorsque Mysql renvoit une ligne de la première table, il renvoit aussi *toutes* les lignes de la seconde table qui lui correspondent.
    Donc si je comprends bien, plusieurs requêtes ?
    C'est dommage, ça aurait été une fonctionnalité vraiment utile.





    Second point, tu dis que les résultats sont déja dans un tableau. Là je ne comprends pas : Quel tableau ?
    Si je fais "$rang=mysql_fetch_row($resultat)", "$rang" ne contient bien qu'une seule ligne ?

  11. #11
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par vampiloup
    Donc si je comprends bien, plusieurs requêtes ?
    C'est dommage, ça aurait été une fonctionnalité vraiment utile.
    Au risque de me répéter : oui, plusieurs requêtes si tu rapatries tout un tas de données. S'il s'agit juste d'avoir les identifiants des personnes en relation avec les identifiants des maisons pour ensuite cliquer sur une personne et avoir une page de détail, une requête suffit...

    Second point, tu dis que les résultats sont déja dans un tableau. Là je ne comprends pas : Quel tableau ?
    Si je fais "$rang=mysql_fetch_row($resultat)", "$rang" ne contient bien qu'une seule ligne ?
    Je rectifie : les résultats sont dans un objet contenant des tableaux. Toujours est-il que si on a ce résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Ligne 1 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom]=Durand ; [prenom]=David
    Ligne 2 : [ID]=16 ; [numero]=47 ; [rue]=rue des magnolias ; [nom]=Durand ; [prenom]=Laurent
    on est absolument pas obligé de reconstruire un tableau pour le traiter. Comme tu dis, un simple mysql_fetch_row/array() suffit.
    Pensez au bouton

Discussions similaires

  1. Réponses: 6
    Dernier message: 05/08/2006, 10h54
  2. [SQL] Récupérer plusieurs lignes spécifiques d'une table
    Par Anduriel dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 29/04/2006, 19h49
  3. Réponses: 2
    Dernier message: 30/11/2005, 09h55
  4. Select case est-il possible dans ce cas ?
    Par rangernoir dans le forum Access
    Réponses: 10
    Dernier message: 30/09/2005, 16h06
  5. Nombre de ligne maxi dans une table ACCESS
    Par ygiraudeau dans le forum Access
    Réponses: 2
    Dernier message: 05/09/2005, 17h23

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