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

Langage SQL Discussion :

Problème de distinct / Max / Group By


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    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)

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    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
    Merci d'ajouter un sur les tags qui vous ont aidé

  4. #4
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    Par défaut
    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

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WHERE [Date validite] >= date()
    cela éliminerait la formation du 11/10/2009
    Merci d'ajouter un sur les tags qui vous ont aidé

  6. #6
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    Par défaut
    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.

  7. #7
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    on peut évidemment faire des trucs un peu plus fin pour cette sélection
    , ex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WHERE year([Date validite]) >= year(date())
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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...
    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
    Merci d'ajouter un sur les tags qui vous ont aidé

  8. #8
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    Par défaut
    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é.

  9. #9
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Bonjour,

    quel est votre SGBD ?

  10. #10
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    Par défaut
    Bonjour,

    Je travaille actuellement sur Access 2007

  11. #11
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    bonjour PunkOff, cela sent le access


    et en utilisant une sous-requête ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Merci d'ajouter un sur les tags qui vous ont aidé

  12. #12
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    Par défaut
    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

  13. #13
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    je voyais tout bêtement, je dis bien tout bêtement , celle-là (celle que tu utilisais) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 :]
    Merci d'ajouter un sur les tags qui vous ont aidé

  14. #14
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    Pourrais-tu fournir un script de cette partie avec quelques données ?

    afin de créer cette base et la tester
    Merci d'ajouter un sur les tags qui vous ont aidé

  15. #15
    Candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 22
    Points : 4
    Points
    4
    Par défaut
    J'ai donc essayé de faire la requête donnée par un membre du forum,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 ...;

Discussions similaires

  1. Problème SELECT, CASE et Group by
    Par Royd938 dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 03/10/2014, 07h41
  2. MAX, GROUP BY et incapassité à nommer clairement le problème
    Par Zoltanogratto dans le forum Requêtes
    Réponses: 1
    Dernier message: 15/06/2013, 21h13
  3. Requête max group by problème
    Par Erakis dans le forum Langage SQL
    Réponses: 10
    Dernier message: 22/02/2008, 14h34
  4. [Cognos 6][Impromptu] Problème avec les champs groupés
    Par nicoduhavre dans le forum Cognos
    Réponses: 4
    Dernier message: 23/03/2007, 15h27
  5. JNDI-LDAP - problème d'affichage de groupes
    Par sangei dans le forum API standards et tierces
    Réponses: 9
    Dernier message: 20/04/2006, 14h38

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