Précédent   Forum des professionnels en informatique > Bases de données > MySQL > Requêtes
Requêtes Forum d'entraide sur les requêtes MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 06/06/2011, 17h03   #1
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
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 :
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 :
DISTINCT SUM(DISTINCT pt.temp_reel) AS total_xp
Le code se présente actuellement sous cette forme en php

Code :
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
Type de fichier : rar urban.rar (26,7 Ko, 4 affichages)
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/06/2011, 20h35   #2
Membre habitué
 
Avatar de tfc3146
 
Homme Robert Labrousse
Développeur décisionnel
Inscription : février 2009
Messages : 79
Détails du profil
Informations personnelles :
Nom : Homme Robert Labrousse
Localisation : France

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

Informations forums :
Inscription : février 2009
Messages : 79
Points : 134
Points : 134
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 :
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,
__________________
Citation:
C'est en faisant n'importe quoi qu'on devient n'importe qui
Si un message vous a aidé, n'hésitez pas à mettre +1
tfc3146 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 09h15   #3
ced
Rédacteur/Modérateur

 
Avatar de ced
 
Homme Cédric Duprez
Inscription : avril 2002
Messages : 3 823
Détails du profil
Informations personnelles :
Nom : Homme Cédric Duprez
Âge : 36
Localisation : France, Loiret (Centre)

Informations professionnelles :
Secteur : Agroalimentaire - Agriculture

Informations forums :
Inscription : avril 2002
Messages : 3 823
Points : 6 440
Points : 6 440
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 :
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/
__________________
Rédacteur / Modérateur SGBD
Mes tutoriels et la FAQ MySQL

----------------------------------------------------
Pensez aux balises code et au tag
Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça
ced est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 12h03   #4
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
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 :
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
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/06/2011, 13h41   #5
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

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

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
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 ?
__________________
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)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 14h33   #6
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
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 :
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
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/06/2011, 14h44   #7
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

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

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
Avec le GROUP BY, c'est sûr que tu ne risques pas de voir les doublons qui se cachent derrière les jointures.
__________________
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)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 14h57   #8
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
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

Citation:
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?
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/06/2011, 15h19   #9
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

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

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
Si tu obtiens la même chose avec ou sans GROUP BY, ce dont je doute, pourquoi faire un GROUP BY ?
__________________
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)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 17h07   #10
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
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 ^^
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/06/2011, 17h56   #11
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

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

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
dans la deuxième requête si tu laisses SUM sans GROUP BY, ça devient du grand n'importe quoi.
__________________
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)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 18h07   #12
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
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
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/06/2011, 19h52   #13
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

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

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
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.
__________________
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)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/06/2011, 21h23   #14
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
Tout est dans post

La requête que je fais :

Citation:
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
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/06/2011, 10h14   #15
ced
Rédacteur/Modérateur

 
Avatar de ced
 
Homme Cédric Duprez
Inscription : avril 2002
Messages : 3 823
Détails du profil
Informations personnelles :
Nom : Homme Cédric Duprez
Âge : 36
Localisation : France, Loiret (Centre)

Informations professionnelles :
Secteur : Agroalimentaire - Agriculture

Informations forums :
Inscription : avril 2002
Messages : 3 823
Points : 6 440
Points : 6 440
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 :
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
__________________
Rédacteur / Modérateur SGBD
Mes tutoriels et la FAQ MySQL

----------------------------------------------------
Pensez aux balises code et au tag
Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça
ced est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 08/06/2011, 11h32   #16
Candidat au titre de Membre du Club
 
Inscription : janvier 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 56
Points : 13
Points : 13
Ç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à )
healou est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 20h19.


 
 
 
 
Partenaires

Hébergement Web