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 :

Requete select sur 2 tables => doublons


Sujet :

Requêtes MySQL

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Par défaut Requete select sur 2 tables => doublons
    Bonjour à tous,

    Je débute sur MySql (version 5), et j'ai un pb avec une requete un peu compliquée (pour moi !).

    Voici ma requete :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT tbContacts.IDClient, tbContacts.IDEntreprise, tbContacts.IDContact, tbContacts.Civilite, tbContacts.Nom, tbContacts.Prenom, tbContacts.CodePostal ContCP, tbContacts.Ville ContVille, tbContacts.TelFixePro, tbContacts.TelMobilePro, tbContacts.EmailPro, tbContacts.TelFixePerso, tbContacts.TelMobilePerso, tbContacts.EmailPerso, 
    tbEntreprises.RaisonSociale, tbEntreprises.TelStandard, tbEntreprises.FaxStandard, tbEntreprises.EmailStandard, tbEntreprises.CodePostal EntCP, tbEntreprises.Ville EntVille
    FROM tbContacts,tbEntreprises
    WHERE tbContacts.IDClient=106 AND tbEntreprises.IDClient=106 AND (tbEntreprises.IDEntreprise = tbContacts.IDEntreprise OR tbContacts.IDEntreprise = 0)
    En fait, ça marche, SAUF QUE :

    • si un contact existe mais n'est pas affecté à une entreprise (tbContacts.IDEntreprise = 0), la requete "doublonne" ce contact autant de fois que le nombre d'entreprises retournées !
    • Si j'enlève la clause "OR tbContacts.IDEntreprise = 0" dans la clause WHERE, les contacts non affectés à une entreprise ne sont pas retournés par la requete.
    • J'ai aussi essayé d'ajouter "DISTINCT" aprés le SELECT, mais ça ne change rien !


    Auriez-vous une idée de ce qui coince ?

    Merci d'avance pour votre aide !

  2. #2
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    • si un contact existe mais n'est pas affecté à une entreprise (tbContacts.IDEntreprise = 0), la requete "doublonne" ce contact autant de fois que le nombre d'entreprises retournées !
    • Si j'enlève la clause "OR tbContacts.IDEntreprise = 0" dans la clause WHERE, les contacts non affectés à une entreprise ne sont pas retournés par la requete.
    Il faut utiliser des jointures normalisées, et notamment la jointure externe...
    http://sqlpro.developpez.com/cours/sqlaz/jointures/
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Par défaut
    Merci pour la réponse.
    Je suis allé voir le lien que tu m'as proposé et ai transformé ma requête en suivant les règles de jointure externe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT tbContacts.IDClient, tbContacts.IDEntreprise, tbContacts.IDContact, tbContacts.Civilite, tbContacts.Nom, tbContacts.Prenom, tbContacts.CodePostal ContCP, tbContacts.Ville ContVille, tbContacts.TelFixePro, tbContacts.TelMobilePro, tbContacts.EmailPro, tbContacts.TelFixePerso, tbContacts.TelMobilePerso, tbContacts.EmailPerso, 
    tbEntreprises.RaisonSociale, tbEntreprises.TelStandard, tbEntreprises.FaxStandard, tbEntreprises.EmailStandard, tbEntreprises.CodePostal EntCP, tbEntreprises.Ville EntVille
    FROM tbContacts 
    LEFT OUTER JOIN tbEntreprises ON tbContacts.IDClient = tbEntreprises.IDClient AND tbContacts.IDEntreprise = tbEntreprises.IDEntreprise 
    WHERE tbContacts.IDClient=106 AND tbEntreprises.IDClient=106
    Le pb, c'est que ça ne me renvoie toujours que les contacts affectés à une entreprise, alors que je les veux tous.

    Ou me suis-je trompé ?

  4. #4
    Membre Expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Par défaut
    Citation Envoyé par Lamanne Voir le message
    Le pb, c'est que ça ne me renvoie toujours que les contacts affectés à une entreprise, alors que je les veux tous.

    Ou me suis-je trompé ?
    Si tu laisses ta clause WHERE aussi restrictive
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE tbContacts.IDClient=106 AND tbEntreprises.IDClient=106
    le résultat restera confiné à cette valeur.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Par défaut
    La valeur "106" est là pour simplifier. Cette valeur est paramétrée dans mon code.

    Le problème n'est pas là.

    En terme de structure, j'ai :

    CLIENTS
    => ENTREPRISES
    => CONTACTS
    => CONTACTS SANS ENTREPRISE

    Les contacts dépendant d'une entreprise et les contacts sans entreprise sont dans la même table "tbContacts".

    Pour les contacts sans entreprise, le champ "IDEntreprise" est à 0.

    L'IDClient "106" sert à limiter les réponses aux données du client identifié par "106" pour les besoins du test.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Par défaut Mille pardons
    Mille pardons !

    Vous m'avez mis la puce à l'oreille sur la condition WHERE...

    J'ai supprimé la clause WHERE sur tbEntreprises.IDEntreprise comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT tbContacts.IDClient, tbContacts.IDEntreprise, tbContacts.IDContact, tbContacts.Civilite, tbContacts.Nom, tbContacts.Prenom, tbContacts.CodePostal ContCP, tbContacts.Ville ContVille, tbContacts.TelFixePro, tbContacts.TelMobilePro, tbContacts.EmailPro, tbContacts.TelFixePerso, tbContacts.TelMobilePerso, tbContacts.EmailPerso, 
    tbEntreprises.RaisonSociale, tbEntreprises.TelStandard, tbEntreprises.FaxStandard, tbEntreprises.EmailStandard, tbEntreprises.CodePostal EntCP, tbEntreprises.Ville EntVille
    FROM tbContacts 
    LEFT OUTER JOIN tbEntreprises ON tbContacts.IDClient = tbEntreprises.IDClient AND tbContacts.IDEntreprise = tbEntreprises.IDEntreprise 
    WHERE tbContacts.IDClient=106
    et Oh miracle : ça fonctionne !

    Merci infiniment pour votre aide !

  7. #7
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    Voici ta requête avec des alias et quelques sauts de ligne supplémentaires pour la rendre plus lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT c.IDClient, c.IDEntreprise,
        c.IDContact, c.Civilite, c.Nom, c.Prenom,
        c.CodePostal ContCP, c.Ville ContVille, 
        c.TelFixePro, c.TelMobilePro, c.EmailPro,
        c.TelFixePerso, c.TelMobilePerso, c.EmailPerso, 
        e.RaisonSociale, 
        e.TelStandard, e.FaxStandard, e.EmailStandard, 
        e.CodePostal EntCP, e.Ville EntVille
    FROM tbContacts c
    LEFT OUTER JOIN tbEntreprises e ON c.IDClient = e.IDClient AND c.IDEntreprise = e.IDEntreprise 
    WHERE c.IDClient=106 AND e.IDClient=106
    Comme la condition de jointure est double avec un AND, les contacts avec IDEntreprise = 0 n'auront pas de correspondance dans la table tbEntreprise et le SGBD mettra NULL sur toutes les colonnes issues de tbEntreprise, y compris e.IDClient, même si c.IDClient existe dans tbEntreprise.

    Comme la restriction supprime toutes les lignes qui n'ont pas e.IDClient = 106, les contacts avec IDClient = 106 mais IDEntreprise = 0 sont éliminés.

    Tu devrais essayer avec un OR dans la double condition de jointure à la place du AND, ou bien ne faire la condition de jointure que sur IDClient.

    EDIT : Argh ! Trop tard !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Par défaut
    Merci CinéPhil !

    Apparemment, j'ai trouvé la solution, mais ce qui m'ennuie, c'est que je ne comprends pas vraiment pourquoi ça fonctionne avec la modif que j'ai indiquée plus tôt !

    Enfin, l'essentiel, c'est que ça fonctionne...

    Mais si tu comprends pourquoi, je suis intéressé par une explication (pas trop technique, si possible !)

  9. #9
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    Et bien l'explication est dans mon précédent message !
    Ce que j'ai préconisé pour la clause de jointure peut apparemment s'appliquer aussi à la clause de restriction.

    D'ailleurs, je serais curieux de savoir si ma solution fonctionnait aussi ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Requete select sur plusieurs tables
    Par cl@ndestIno dans le forum Langage SQL
    Réponses: 3
    Dernier message: 15/12/2008, 12h36
  2. Requete mysql : select sur deux tables
    Par IP-Fix dans le forum Requêtes
    Réponses: 9
    Dernier message: 12/11/2008, 16h03
  3. requete SELECT sur 3 tables
    Par TheBlackReverand dans le forum Langage SQL
    Réponses: 3
    Dernier message: 29/01/2008, 12h53
  4. Requete select sur 2 tables
    Par beho dans le forum Requêtes
    Réponses: 3
    Dernier message: 13/02/2007, 15h19
  5. Requete SELECT SUR +sieurs tables
    Par yanis97 dans le forum Langage SQL
    Réponses: 5
    Dernier message: 21/09/2006, 13h30

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