Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
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 07/07/2011, 12h26   #1
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
Par défaut Problème de distinct / Max / Group By

Bonjour à tous,

Je suis actuellement en train de faire la gestion des formations des employés d'une entreprise sur access.

Je dois donc, pour certains employés, sortir une carte d'autorisation de conduite d'engins de chantier (caces, etc...), sur laquelle je dois faire figurer la liste des formations qu'ils ont passées, avec le libellé raccourci de la formation, la date d'obtention et la date de validité (les formations ne sont valides que 5 ou 10 selon ces dernières).

J'ai donc plusieurs tables dans ma base :



(Merci de ne pas critiquer les accents, espaces et autres ponctuations bizarres sur les noms des tables et des champs, ce n 'est pas moi qui les ai fait :)

Donc je tente de faire la liste des formations pour un employé précis, après je me débrouillerai pour les autres ; il faut donc les trois champs mentionéees ci-dessus, à savoir "abréviation", "date session", "à refaire avant le :", où abréviation est l'abréviation du libellé de la formation.

J'avais donc fait cette requête là:
Code :
1
2
3
4
5
6
7
8
9
10
 SELECT abréviation, [intervenant (société)], [date session], [à refaire avant le :], [code salarié]
FROM[liste des salariés] AS ls,[liste des formations] AS lf, [sessions de formation] AS sf, [session-participants] AS sp, intervenants AS i
WHERE ls.[code salarié] = sp.[rappel code salarié] 
AND sp.[rappel n° session] = sf.[n° session] 
AND sf.[rappel n° formation] = lf.[n° formation] 
AND i.[n° intervenant] = sf.[n° intervenant] 
AND abréviation IS NOT NULL 
AND [présence salarié] = "présent" 
AND year([à refaire avant le :]) >= year(date())
ORDER BY [date session], abréviation;
Or il se trouve que quand je fais ça, il me sort toutes les mêmes formations, je m'explique : par exemple, si une formation se périme en 2011 et que la formation pour la refaire a été faite en 2011, il me sortira ces deux formations. Le problème est que je ne veux seulement qu'une seule formation (à savoir celle réalisée il y a le moins longtemps, donc la plus récente) par type de formation (ne pas avoir deux fois caces r372M, etc..).

J'ai tenté un millier de requêtes avec des "distinct", des "max", il me sort toujours deux formations identiques mais qui ont des dates différentes, à cause du group by.

Code :
1
2
3
4
5
6
7
8
 SELECT abréviation, [date session], [à refaire avant le :]
FROM[liste des salariés] ls, [session-participants] sp,[liste des formations] lf, [sessions de formation] sf
WHERE ls.[code salarié] = sp.[rappel code salarié]
AND sp.[rappel n° session] = sf.[n° session]
AND lf.[n° formation] = sf.[rappel n° formation]
AND [code salarié] = "1015"
AND abréviation IS NOT NULL
GROUP BY abréviation, [date session], [à refaire avant le :]

Ce qui me donne :



Il faudrait donc que le "Caces catégorie 3B R386 n'apparaisse qu'une fois, avec la date de validité la plus récente.

Or quand je fais la même requête en supprimant simplement le "[à refaire avant le :]", la requête fonctionne et ne me met que 6 résultats au lieu de 7, mais je n'ai pas d'informations concernant la date de validité, c'est donc un peu le bazar...

Quelqu'un pourrait-il m'aider s'il vous plaît ?

Cordialement,

Anthony
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 12h35   #2
Membre Expert
 
Avatar de Yanika_bzh
 
Homme Yannick
Ingénieur Etudes & Developpements
Inscription : février 2006
Messages : 1 125
Détails du profil
Informations personnelles :
Nom : Homme Yannick
Localisation : France, Deux Sèvres (Poitou Charente)

Informations professionnelles :
Activité : Ingénieur Etudes & Developpements
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2006
Messages : 1 125
Points : 1 670
Points : 1 670
regardez du coté de la clause HAVING

Bon courage
__________________
Dans la connaissance du monde, ceux qui ne savent rien en savent toujours autant que ceux qui n'en savent pas plus qu'eux. (Pierre Dac)
Yanika_bzh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h04   #3
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
et pensez, pour les jointures, à utiliser la syntaxe "moderne", i.e. celle utilisant le INNER JOIN pour les requêtes internes.

Cela rend (entres autres) la lecture des requêtes, et donc leurs analyses, plus faciles
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h13   #4
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
Bonjour, j'ai déjà essayé avec le having et le résultat est le même...

Sinon pour les jointures, je m'excuse mais j'ai commencé la programmation l'année dernière et on nous a appris à les faire de cette manière en cours... je ne comprends rien au inner join etc...

Merci quand même pour vos réponses
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h28   #5
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
Citation:
Sinon pour les jointures, je m'excuse mais j'ai commencé la programmation l'année dernière et on nous a appris à les faire de cette manière en cours... je ne comprends rien au inner join etc...
Soupir


exemple pour le INNER JOIN
au lieu de :
Code :
1
2
3
SELECT .....
FROM[liste des salariés] AS ls, [session-participants] AS sp
WHERE ls.[code salarié]=sp.[rappel code salarié]
faire :
Code :
1
2
3
SELECT .....
FROM[liste des salariés] AS ls
  INNER JOIN [session-participants] AS sp ON (ls.[code salarié]=sp.[rappel code salarié])
c'est tout

et pour problème plus direct.
Pourquoi ne pas exclure les "formations" dont la "date de validité" est dépassée ?
Code :
1
2
 
WHERE [Date validite] >= date()
cela éliminerait la formation du 11/10/2009
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/07/2011, 13h31   #6
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
Car les secrétaires veulent garder les formations se terminant dans l'année, vu que quand une formation arrive à échéance, le salarié a l'année entière pour la refaire.

Sinon je l'avais déjà fait et c'est vrai que ça marche, sauf si la formation se termine durant la même année que commence la nouvelle.
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h38   #7
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
on peut évidemment faire des trucs un peu plus fin pour cette sélection
, ex
Code :
1
2
 
WHERE year([Date validite]) >= year(date())
ou
Code :
1
2
 
WHERE year([Date validite]) >= year(date()) - 1
etc...

mais dans ce cas, la même formation peut apparaitre plusieurs fois, et c'est normal...
Citation:
Car les secrétaires veulent garder les formations se terminant dans l'année, vu que quand une formation arrive à échéance, le salarié a l'année entière pour la refaire.
on affiche l'ancienne formation ET la nouvelle
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h41   #8
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
Oui je l'avais fait, mais l'idéal serait que la formation la plus récente n'apparaisse qu'une fois par type de formation. Je me débrouille toujours en SQL en temps normal mais il est vrai que pour cette problématique là je n'y arrive pas, et je ne vois surtout pas comment faire, ayant quasiment tout essayé.
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h46   #9
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
Bonjour,

quel est votre SGBD ?
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h53   #10
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
Bonjour,

Je travaille actuellement sur Access 2007
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 13h56   #11
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
bonjour PunkOff, cela sent le access


et en utilisant une sous-requête ?
Code :
1
2
3
4
5
 
SELECT ....., MAX(A.[Date validite])
FROM ("sous-requete de selection" AS A)
    INNER JOIN "MEME sous-requete de selection" AS B (A.abréviation = B.abréviation)
GROUP BY ......
c'est juste une piste
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 14h02   #12
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
Et je mettrais quoi dans le sous-requête de sélection ??

PS: j'ai déjà essayé les requêtes imbriquées et même avec ça ça ne marche pas
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/07/2011, 14h38   #13
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
je voyais tout bêtement, je dis bien tout bêtement , celle-là (celle que tu utilisais) :
Code :
1
2
3
4
5
6
7
8
9
 
SELECT abréviation, [date session], [à refaire avant le :]
FROM[liste des salariés] ls, [session-participants] sp,[liste des formations] lf, [sessions de formation] sf
WHERE ls.[code salarié] = sp.[rappel code salarié]
AND sp.[rappel n° session] = sf.[n° session]
AND lf.[n° formation] = sf.[rappel n° formation]
AND [code salarié] = "1015"
AND abréviation IS NOT NULL
GROUP BY abréviation, [date session], [à refaire avant le :]
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/07/2011, 08h16   #14
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
Pourrais-tu fournir un script de cette partie avec quelques données ?

afin de créer cette base et la tester
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/07/2011, 13h09   #15
Invité de passage
 
Inscription : juillet 2011
Messages : 21
Détails du profil
Informations forums :
Inscription : juillet 2011
Messages : 21
Points : 0
Points : 0
J'ai donc essayé de faire la requête donnée par un membre du forum,

Code :
1
2
3
4
5
6
7
8
9
10
11
SELECT lf.abréviation, sf.[date session], sf.[à refaire avant le :]
FROM ((SELECT  lf.abréviation, max(sf.[à refaire avant le :]) AS maxi
FROM (([session-participants] AS sp
INNER JOIN [sessions de formation] AS sf ON sp.[rappel N° session] = sf.[N° session])
INNER JOIN[liste des formations] AS lf ON sf.[rappel N° formation] = lf.[N° formation])
 INNER JOIN[liste des salariés] AS ls ON sp.[rappel code salarié] = ls.[code salarié]
 WHERE ((lf.[abréviation]) IS NOT NULL))
GROUP BY lf.abréviation)  AS A
INNER JOIN[liste des formations] AS lf ON A.[abréviation] = lf.[abréviation])
 
INNER JOIN [sessions de formation] AS sf ON lf.[N° formation] = sf.[rappel N° formation] AND sf.[à refaire avant le :] = A.Maxi;
Mais dessus, il me faudrait également dans le select le champs [code salarié] ainsi que le champ [intervenant (société)], chose que j'essaye de faire depuis ce matin ...;
Thony3351 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h48.


 
 
 
 
Partenaires

Hébergement Web