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 :

problème d'incompréhension avec les jointures


Sujet :

Requêtes MySQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut problème d'incompréhension avec les jointures
    Bonjour à tous,

    Voici mon problème, j'essaye de faire une requête afin de récupérer des informations des candidats qui ont laisser un cv sur le site.


    Le problème est que, dès que je rentre cette ligne dans la requête, l'un des 2 candidats disparait alors qu'il devrait être présent.

    Voici la requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT  c.id as id,c.nom as nom,c.prenom as prenom,
    DAY(c.date_envois) as Jour, MONTH(c.date_envois) as Mois, YEAR(c.date_envois) as Annee,
    s.nom as nom_secteur,
    a.titre as titre_annonce,
    DISTINCT SUM(DISTINCT pt.temp_reel) As total_xp
    FROM postule_candidat  AS c
    LEFT JOIN secteur AS s                      ON s.id              = c.fk_id_secteur
    LEFT JOIN annonce As a                      ON a.fk_id_job       = c.fk_id_post
    LEFT JOIN job As j                          ON j.id              = a.fk_id_job
    LEFT JOIN postule_diplome_candidat  As dc   ON dc.fk_id_candidat = c.id
    LEFT JOIN postule_experience_candidat As ec ON ec.fk_id_candidat = c.id
    LEFT JOIN postule_temp As pt                ON pt.id             = ec.fk_id_temp
    WHERE c.id > 0
    La ligne qui fait tout foirer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DISTINCT SUM(DISTINCT pt.temp_reel) As total_xp
    Le code se présente actuellement sous cette forme en php

    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php
    $candidat = new Candidat();
     
    $requete =          ' SELECT  c.id as id,c.nom as nom,c.prenom as prenom,';
    $requete = $requete.' DAY(c.date_envois) as Jour, MONTH(c.date_envois) as Mois, YEAR(c.date_envois) as Annee,';
    $requete = $requete.' s.nom as nom_secteur,';
    $requete = $requete.' a.titre as titre_annonce,';
    $requete = $requete.' SUM(DISTINCTpt.temp_reel) As total_xp';
    $requete = $requete.' FROM postule_candidat  AS c';
    $requete = $requete.' LEFT JOIN secteur AS s                      ON s.id   fk_id_type_diplome  = '.$_POST["diplome_type"].')';
     
    if(!empty($_POST["fonction"])) $requete = $requete.' AND (ec.fk_id_diplome = '.$_POST["fonction"].')';
    $requete = $requete.' ORDER BY j.date_creation DESC';
    ?>
               = c.fk_id_secteur';
    $requete = $requete.' LEFT JOIN annonce As a                      ON a.fk_id_job       = c.fk_id_post';
    $requete = $requete.' LEFT JOIN job As j                          ON j.id              = a.fk_id_job';
    $requete = $requete.' LEFT JOIN postule_diplome_candidat  As dc   ON dc.fk_id_candidat = c.id';
    $requete = $requete.' LEFT JOIN postule_experience_candidat As ec ON ec.fk_id_candidat = c.id';
    $requete = $requete.' LEFT JOIN postule_temp As pt                ON pt.id             = ec.fk_id_temp';
    $requete = $requete.' WHERE c.id > 0';
    if(!empty($_POST["diplome_type"])) $requete = $requete.' AND (dc.fk_id_type_diplome  = '.$_POST["diplome_type"].')';
     
    if(!empty($_POST["fonction"])) $requete = $requete.' AND (ec.fk_id_diplome = '.$_POST["fonction"].')';
    $requete = $requete.' ORDER BY j.date_creation DESC';
    ?>
    Ce sont des requêtes crées dans la page php pour faire du multi requête par select.

    Je vous fournis également la base de données en pièce jointe

    Merci d'avance pour l'aide, car je sèche dessus depuis ce matin ^^
    Si vous avez des conseils pour optimiser ma requête, n'hésitez pas ^^
    Fichiers attachés Fichiers attachés

  2. #2
    Membre habitué Avatar de tfc3146
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Février 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Février 2009
    Messages : 79
    Points : 150
    Points
    150
    Par défaut
    Bonsoir,

    Il n'y a pas de DISTINCT avec les fonctions d'agrégation.

    Je ne sais pas à quoi correspond vos attributs, ce qui pourrait nous aider à comprendre à quel niveau vous voulez agrégez vos données.

    De plus, ce n'est pas utile de mettre des alias sur des colonnes si c'est pour les renommer pareil

    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
    SELECT  c.id,c.nom,c.prenom, DAY(c.date_envois) AS Jour, MONTH(c.date_envois) AS Mois, YEAR(c.date_envois) AS Annee,
    s.nom AS nom_secteur,
    a.titre AS titre_annonce,
    SUM(pt.temp_reel) AS total_xp
    FROM postule_candidat  AS c
    LEFT JOIN secteur AS s                      ON s.id              = c.fk_id_secteur
    LEFT JOIN annonce AS a                      ON a.fk_id_job       = c.fk_id_post
    LEFT JOIN job AS j                          ON j.id              = a.fk_id_job
    LEFT JOIN postule_diplome_candidat  AS dc   ON dc.fk_id_candidat = c.id
    LEFT JOIN postule_experience_candidat AS ec ON ec.fk_id_candidat = c.id
    LEFT JOIN postule_temp AS pt                ON pt.id             = ec.fk_id_temp
    WHERE c.id > 0
    GROUP BY c.id,c.nom,c.prenom,
    DAY(c.date_envois), MONTH(c.date_envois), YEAR(c.date_envois),s.nom,a.titre,

  3. #3
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 034
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 034
    Points : 23 779
    Points
    23 779
    Par défaut
    Bonjour,

    Dans ta requête, il y a des jointures qui ne servent à rien. Autant les retirer pour ne pas alourdir la syntaxe.
    Il manque également le GROUP BY, qui, compte tenu de ton schéma et du fait que tu es sous MySQL, peut se réduire au seul c.id (tous les autres champs du SELECT en dehors de la fonction SUM dépendant fonctionnellement de cet id).
    Ce qui donne la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT  c.id AS id,c.nom AS nom,c.prenom AS prenom,
    DAY(c.date_envois) AS Jour, MONTH(c.date_envois) AS Mois, YEAR(c.date_envois) AS Annee,
    s.nom AS nom_secteur,
    a.titre AS titre_annonce
    , SUM(DISTINCT pt.temp_reel) AS total_xp
    FROM postule_candidat  AS c
    LEFT JOIN secteur AS s                      ON s.id              = c.fk_id_secteur
    LEFT JOIN annonce AS a                      ON a.fk_id_job       = c.fk_id_post
    LEFT JOIN postule_experience_candidat AS ec ON ec.fk_id_candidat = c.id
    LEFT JOIN postule_temp AS pt                ON pt.id             = ec.fk_id_temp
    WHERE c.id > 0
    GROUP BY c.id
    Pour plus de détails sur la raison du seul c.id dans le GROUP BY, voir l'article suivant : http://cedric-duprez.developpez.com/...fier-group-by/

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    merci pour vos réponses

    les alias me servent dans la récupération php^^
    pour cette ligne ci

    SUM(DISTINCT pt.temp_reel)

    J'ai mis distinct car la valeur était erronée, mais avec distinct elle l'est toujours :s

    si l'on regarde dans la table postule_experience_candidat

    pour pour le candidat n° 16 j'ai 1,18
    pour pour le candidat n° 18 j'ai 4,16


    sans le distinct j'obtiens

    pour pour le candidat n° 16 j'ai 57
    pour pour le candidat n° 18 j'ai 18


    avec le distinct j'obtiens

    pour pour le candidat n° 16 j'ai 19
    pour pour le candidat n° 18 j'ai 18


    alors que le 2eme candidat dans les 2 cas devrait me renvoyer 20 :/

    la requête qui m'a permis d'avoir ces résultats est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT  c.id AS id,c.nom AS nom,c.prenom AS prenom,
    DAY(c.date_envois) AS Jour, MONTH(c.date_envois) AS Mois, YEAR(c.date_envois) AS Annee,
    s.nom AS nom_secteur,
    a.titre AS titre_annonce
    , SUM(DISTINCT pt.temp_reel) AS total_xp
    FROM postule_candidat  AS c
    LEFT JOIN secteur AS s                      ON s.id              = c.fk_id_secteur
    LEFT JOIN annonce AS a                      ON a.fk_id_job       = c.fk_id_post
    LEFT JOIN postule_experience_candidat AS ec ON ec.fk_id_candidat = c.id
    LEFT JOIN postule_temp AS pt                ON pt.id             = ec.fk_id_temp
    WHERE c.id > 0
    GROUP BY c.id
    ORDER BY c.date_envois DESC

  5. #5
    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 : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Saluton,
    Est-ce que c.date_envois est le même pour toutes les lignes des c.id du GROUP BY ?
    De même, est-ce que s.id, a.fk_id_job, ec.fk_id_candidat, ne produisent pas, via les jointures, des doublons de pt.temp_reel dans le GROUP BY ?

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    Ben en fait j'en sais absolument rien, j'ai jamais dépasse auparavant une jointure a 2-3 tables, et je n'ai jamais eu a faire à des doublons

    avec cette requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT  c.id AS id,c.nom AS nom,c.prenom AS prenom,
    DAY(c.date_envois) AS Jour, MONTH(c.date_envois) AS Mois, YEAR(c.date_envois) AS Annee,
    s.nom AS nom_secteur,
    a.titre AS titre_annonce
    , SUM(DISTINCT pt.temp_reel) AS total_xp
    FROM postule_candidat  AS c
    LEFT JOIN secteur AS s                      ON s.id              = c.fk_id_secteur
    LEFT JOIN annonce AS a                      ON a.fk_id_job       = c.fk_id_post
    LEFT JOIN postule_experience_candidat AS ec ON ec.fk_id_candidat = c.id
    LEFT JOIN postule_temp AS pt                ON pt.id             = ec.fk_id_temp
    WHERE c.id > 0
    GROUP BY c.id
    ORDER BY c.date_envois DESC
    j'obtiens ceci:

    id nom prenom Jour Mois Annee nom_secteur titre_annonce total_xp
    18 dupont cedric 6 6 2011 Designer Senior Design Engineer HVAC 19
    16 francis seb 6 6 2011 NULL NULL 18


    si je retire le group by j'obtiens

    id nom prenom Jour Mois Annee nom_secteur titre_annonce total_xp
    16 francis seb 6 6 2011 NULL NULL 37


    il n'y a pas l'air d'avoir de doublons

  7. #7
    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 : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Avec le GROUP BY, c'est sûr que tu ne risques pas de voir les doublons qui se cachent derrière les jointures.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    Citation Envoyé par Maljuna Kris Voir le message
    Avec le GROUP BY, c'est sûr que tu ne risques pas de voir les doublons qui se cachent derrière les jointures.
    c'est pour cela que

    si je retire le group by j'obtiens

    id nom prenom Jour Mois Annee nom_secteur titre_annonce total_xp
    16 francis seb 6 6 2011 NULL NULL 37
    J'aurais des doublons la ligne serait multipliée? non?

  9. #9
    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 : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Si tu obtiens la même chose avec ou sans GROUP BY, ce dont je doute, pourquoi faire un GROUP BY ?

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    Citation Envoyé par healou Voir le message

    avec group by j'obtiens ceci:

    id nom prenom Jour Mois Annee nom_secteur titre_annonce total_xp
    18 dupont cedric 6 6 2011 Designer Senior Design Engineer HVAC 19
    16 francis seb 6 6 2011 NULL NULL 18


    si je retire le group by j'obtiens

    id nom prenom Jour Mois Annee nom_secteur titre_annonce total_xp
    16 francis seb 6 6 2011 NULL NULL 37


    il n'y a pas l'air d'avoir de doublons
    Ça ne renvoit pas la même chose ^^

  11. #11
    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 : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    dans la deuxième requête si tu laisses SUM sans GROUP BY, ça devient du grand n'importe quoi.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    c'est clair ^^ c est pas normale, il devrait me mettre le 2eme normalement :/ (c'était à la base le problème que j'avais)

    Maintenant reste plus cas trouver d’où vient cette erreur de calcul :/

    J'ai beau retirer group by et distinct, il me renvois aucun doublons

  13. #13
    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 : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Citation Envoyé par healou Voir le message
    J'ai beau retirer group by et distinct, il me renvoit aucun doublon
    Qu'en sais-tu ?
    Quelle est au juste la requête ?
    PAr ailleurs, montre-nous un jeu d'essai de données sur les tables concernées.

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    Tout est dans post

    La requête que je fais :

    SELECT c.id AS id,c.nom AS nom,c.prenom AS prenom,
    DAY(c.date_envois) AS Jour, MONTH(c.date_envois) AS Mois, YEAR(c.date_envois) AS Annee,
    s.nom AS nom_secteur,
    a.titre AS titre_annonce
    , SUM(DISTINCT pt.temp_reel) AS total_xp
    FROM postule_candidat AS c
    LEFT JOIN secteur AS s ON s.id = c.fk_id_secteur
    LEFT JOIN annonce AS a ON a.fk_id_job = c.fk_id_post
    LEFT JOIN postule_experience_candidat AS ec ON ec.fk_id_candidat = c.id
    LEFT JOIN postule_temp AS pt ON pt.id = ec.fk_id_temp
    WHERE c.id > 0
    GROUP BY c.id
    ORDER BY c.date_envois DESC
    Toute la base de données est dans le 1er message (format zip) ^^
    merci d avance

  15. #15
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 034
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 034
    Points : 23 779
    Points
    23 779
    Par défaut
    Le total est juste compte tenu de la requête faite.
    En fait, dans les données, pour un même job, il y a eu plusieurs annonces. C'est donc la jointure entre annonce et postule_candidat qui démultiplie le nombre de lignes.
    2 solutions :
    1. Enlever la jointure vers la table annonce ;
    2. Faire une sous-requête pour obtenir le total souhaité.


    Pour la sous-requête, tu peux faire comme ça :
    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
    16
    17
    18
    SELECT c.id AS id, c.nom AS nom, c.prenom AS prenom,
    DAY(c.date_envois) AS Jour, MONTH(c.date_envois) AS Mois, YEAR(c.date_envois) AS Annee,
    s.nom AS nom_secteur,
    a.titre AS titre_annonce,
    t.total_xp
    FROM postule_candidat AS c
    LEFT JOIN secteur AS s ON s.id = c.fk_id_secteur
    LEFT JOIN annonce AS a ON a.fk_id_job = c.fk_id_post
    LEFT JOIN (
      SELECT c2.id, SUM(pt.temp_reel) AS total_xp
      FROM  postule_candidat AS c2
      LEFT JOIN postule_experience_candidat AS ec ON ec.fk_id_candidat = c2.id
      LEFT JOIN postule_temp AS pt ON pt.id = ec.fk_id_temp
      WHERE c2.id > 0
      GROUP BY c2.id
    ) AS t ON c.id = t.id
    WHERE c.id > 0
    ORDER BY c.date_envois DESC

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 42
    Points
    42
    Par défaut
    Ça fonctionne!!!!!
    Merci à tous pour votre aide et vos explications

    Et pour l'erreur de calcul, c'était de ma faute, je comptais le total des id au lieu du contenu 1-18 correspondait en fait à 1-17 (donc 18) et 16-4 à 15-4 (donc 19)

    Désolé pour cette immonde erreur d’inattention (à mon avis, je devais trop avoir la tête dans le cul à ce moment-là )

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

Discussions similaires

  1. [MySQL] Problème avec les jointures
    Par Akim13 dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 29/05/2011, 16h02
  2. Problème avec les jointures
    Par xoum89 dans le forum Langage SQL
    Réponses: 16
    Dernier message: 28/03/2011, 21h41
  3. Problème avec les jointures
    Par exqo77 dans le forum JDBC
    Réponses: 6
    Dernier message: 17/02/2010, 10h06
  4. [MySQL] Problème avec les jointure pour un menu
    Par Glocman dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 31/07/2006, 17h44
  5. Réponses: 2
    Dernier message: 21/07/2005, 12h05

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