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 18/11/2010, 10h14   #1
Candidat au titre de Membre du Club
 
Inscription : août 2006
Messages : 46
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 46
Points : 13
Points : 13
Par défaut SELECT Count et jointure

Bonjour à tous. J'ai 3 tables access:

tblmembres (mbreID, matricule, nom, prenoms, catID)
tblcategories(catID, catLibelle, catDescription, catTaux)
tblcotisations(cotID, cotDate, mbreID, cotmois)

la première table comprend les informations sur les membres d'une association, la seconde contient les catégories de membres (selon la catégorie du membre il y a un montant a cotiser).

La dernière enregistre les cotisations faites par un membre (date de la cotisation, le membre concerné, le mois pour lequel il cotise).

Pour une personne dont on a le matricule, je souhaite avoir sa catégorie, et le nombre total de mois qu'il a cotisé. Voici ma requête:

Citation:
SELECT COUNT (t.cotmois) AS TOTAL,m.matricule, m.nom, m.prenoms, c.catID FROM tblmembres m,tblcategories c, tblcotisations t WHERE (m.mbreID=t.mbreID AND m.catID=c.catID AND matricule='123456' GROUP BY t.cotmois
Mais lorsque j'exécute la requête, je reçois le message "Vous avez essayé d'exécuter une requête ne comprenant pas l'expression spécifiée 'matricule' comme une partie de la fonction d'agrégat"

Je ne vois pas bien ce qui ne vas pas.
Si quelqu'un veut bien m'aider pour trouver une solution.

Merci de votre compréhension
Lynecoln est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 10h33   #2
Membre confirmé
 
Homme AbdelRaouf Gt
Développeur informatique
Inscription : décembre 2009
Messages : 203
Détails du profil
Informations personnelles :
Nom : Homme AbdelRaouf Gt
Âge : 27
Localisation : France

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : décembre 2009
Messages : 203
Points : 238
Points : 238
T'as oubli d'ajouter t.cotmois à ta requête :

Code :
1
2
3
4
5
6
7
  SELECT COUNT(t.cotmois) AS TOTAL,
         t.cotmois, m.matricule, m.nom, m.prenoms, c.catID
    FROM tblmembres m, tblcategories c, tblcotisations t
   WHERE m.mbreID = t.mbreID
     AND m.catID = c.catID
     AND matricule = '123456'
GROUP BY t.cotmois
aguetat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 10h35   #3
Expert Confirmé
 
Avatar de Lyche
 
Homme
Développeur SQL
Inscription : janvier 2007
Messages : 1 957
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur SQL

Informations forums :
Inscription : janvier 2007
Messages : 1 957
Points : 3 849
Points : 3 849
Envoyer un message via MSN à Lyche
Bonjour,

Lorsque tu crées un groupement dans ta requête, ce n'est pas le champ contenu dans le count qu'il faut mettre en agrégat de regroupement.

Code sql :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
SELECT COUNT (t.cotmois) AS TOTAL,
       m.matricule,
       m.nom,
       m.prenoms,
       c.catID
FROM
      tblmembres m,
      tblcategories c,
      tblcotisations t
WHERE
       m.mbreID  = t.mbreID AND
       m.catID   = c.catID  AND
       matricule = '123456'
GROUP BY
         m.matricule,
         m.nom      , 
         m.prenoms  ,
         c.catID

Mais tous les champs qui sont dans le select et qui ne sont pas dans le count.
Je constate que ta requête n'est pas normée, tu devrais regarder du côté des INNER JOIN. Si tu n'es pas familier avec les jointures normées, je te conseil de regarder ici
-> http://sqlpro.developpez.com/cours/sqlaz/jointures/

un très bon tutoriel qui explique bien pourquoi utiliser les jointures et comment s'en servir.

Cordialement.
__________________
Citation:
le programmeur est une machine bizarre qui transforme le café en code et le code en spaghetti
http://lyche.minitroopers.fr Rejoignez nous !
Lyche est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 10h42   #4
Candidat au titre de Membre du Club
 
Inscription : août 2006
Messages : 46
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 46
Points : 13
Points : 13
Merci à aguetat et Lyche pour vos reponses.

J'ai essayer d'ajouter tous les champs qui ne sont pas dans le count comme l'a dit Lyche ety ça marche.

Pour ce qui est de la normalisation, je suis en ce moment même entrain de lire le tuto.

Merci infiniment
Lynecoln est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 10h42   #5
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 615
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 615
Points : 2 593
Points : 2 593
Bonjour,

Voici un petit cours sur la clause "GROUP BY" :
http://sqlpro.developpez.com/cours/sqlaz/ensembles/

Je cite :
De plus, toutes les colonnes représentées hors des calculs d'agrégation doivent figurer dans la clause GROUP BY.

Hors ici vous faites un GROUP BY sur t.cotmois, mais dans votre select vous avez "m.matricule, m.nom, m.prenoms, c.catID" qui ne fait pas partie de votre GROUP BY, du coup le SGBD ne sait pas quoi faire


Pour en revenir à votre requête si vous avez une relation 1-1 entre vos tables tblmembres & tblcategories vous pouvez utiliser "MAX" ou "MIN" pour palier ce problème.

Sinon il faudra passer par une sous requête.


De plus veillez à utilisez la nouvelle syntaxe pour les jointures ce sera plus lisible.

Code :
1
2
3
4
5
6
7
 
SELECT COUNT (t.cotmois) AS TOTAL, m.matricule, max(m.nom), max(m.prenoms), max(c.catID) 
FROM tblmembres m
INNER JOIN tblcategories c ON m.catID=c.catID 
INNER JOIN tblcotisations t m.mbreID=t.mbreID
WHERE m.matricule='123456' 
GROUP BY m.matricule
J'ai aussi changé votre group by, car à la base vous étiez parti pour faire des groupement sur des mois, alors que vous souhaitez avoir des stats par membre distinct.

edit: ah bah y a du monde ce matin ^^
edit 2 : une erreur s'était glissée dans ma requête max(m.matricule) remplacé par m.matricule
punkoff est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 12h40   #6
Candidat au titre de Membre du Club
 
Inscription : août 2006
Messages : 46
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 46
Points : 13
Points : 13
Merci à tous. Après la lecture du tuto et de vos différents postes, j'ai normalisé mon sql.

Mais j'ai une autre préoccupation.

Je veux une requête qui ramène nom, prenoms, nombre de mois cotisés pour tous les membres de l'association (qu'ils aient cotisé ou non). Pour ce qui n'ont rien cotisé (donc ne sont pas dans la table tblcotisations) nombre de mois cotisés est zéro.

J'ai aussi besoin d'un coup de main, car toutes mes tentatives sont vaines
Lynecoln est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 12h56   #7
Expert Confirmé
 
Avatar de Lyche
 
Homme
Développeur SQL
Inscription : janvier 2007
Messages : 1 957
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur SQL

Informations forums :
Inscription : janvier 2007
Messages : 1 957
Points : 3 849
Points : 3 849
Envoyer un message via MSN à Lyche
Il va te falloir une jointure gauche (ou droite) sur la table des collaborateurs. Tu dois d'abord calculer les cotisations pour tous et relier les tables par les identifiants des collaborateurs.

Code :
1
2
3
4
5
6
7
8
9
10
 
SELECT nom    ,
       prenom,
       ISNULL(TotalCotisation, 0)
FROM
       utilisateurs
       LEFT JOIN ( SELECT idMatricule
                          COUNT(moiscotisation)
                   FROM  cotisation ) cotisation
            ON utilisateur.idMatricule = cotisation.idMatricule;
Je n'ai fait qu'un exemple, (certains n'aiment pas les sous requêtes comme je l'ai faite, mais je trouve que c'est plutôt efficace).

Je te laisse le soin de l'adapter à ta requête

Cordialement.
__________________
Citation:
le programmeur est une machine bizarre qui transforme le café en code et le code en spaghetti
http://lyche.minitroopers.fr Rejoignez nous !
Lyche est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 13h04   #8
Candidat au titre de Membre du Club
 
Inscription : août 2006
Messages : 46
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 46
Points : 13
Points : 13
Merci Lyche. Je viens d'essayer quelque chose qui donne les résultats que je veux. Mais je ne sais pas si coté normalisation il est bon ou pas !!!

Code :
1
2
3
4
5
SELECT m.mbreID,max(matricule), max(nom) AS nom, max(prenoms) AS prenoms,max(catLibelle) AS categorie,max(quotamontant) AS quota, count(t.mbreID) AS total  
FROM (
       (tblmembres m  INNER JOIN 
             (tblcategories c INNER JOIN tblquotas q ON q.catID=c.catID) ON m.categorie=c.catID ) 
         LEFT OUTER JOIN tblcotisations t ON m.mbreID=t.mbreID)  GROUP BY m.mbreID
Lynecoln est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 13h11   #9
Expert Confirmé
 
Avatar de Lyche
 
Homme
Développeur SQL
Inscription : janvier 2007
Messages : 1 957
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur SQL

Informations forums :
Inscription : janvier 2007
Messages : 1 957
Points : 3 849
Points : 3 849
Envoyer un message via MSN à Lyche
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
SELECT m.mbreID,
       MAX(matricule)                ,
       MAX(nom)          AS nom      ,
       MAX(prenoms)      AS prenoms  ,
       MAX(catLibelle)   AS categorie,
       MAX(quotamontant) AS quota    ,
       COUNT(t.mbreID)   AS total  
FROM (
       ( tblmembres m
         INNER JOIN ( tblcategories c
                      INNER JOIN tblquotas q
                            ON q.catID = c.catID )
               ON m.categorie = c.catID )
         LEFT OUTER JOIN tblcotisations t
               ON m.mbreID = t.mbreID )
GROUP BY
         m.mbreID;
Soigne juste ton indentation et tu verras tu arriveras toi même à voir si c'est aux normes .
Par contre, je ne comprend pas l'emploi des MAX partout
__________________
Citation:
le programmeur est une machine bizarre qui transforme le café en code et le code en spaghetti
http://lyche.minitroopers.fr Rejoignez nous !
Lyche est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 14h08   #10
Candidat au titre de Membre du Club
 
Inscription : août 2006
Messages : 46
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 46
Points : 13
Points : 13
Les max que j'utilise c'est par rapport au post de punkoff ci-dessous. Sans les max, je suis obligé de mettre les noms de tous les champs dans le GROUP BY

Merci pour ton aide
Lynecoln est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 14h35   #11
Expert Confirmé
 
Avatar de Lyche
 
Homme
Développeur SQL
Inscription : janvier 2007
Messages : 1 957
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur SQL

Informations forums :
Inscription : janvier 2007
Messages : 1 957
Points : 3 849
Points : 3 849
Envoyer un message via MSN à Lyche
De rien
__________________
Citation:
le programmeur est une machine bizarre qui transforme le café en code et le code en spaghetti
http://lyche.minitroopers.fr Rejoignez nous !
Lyche est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2010, 14h54   #12
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 680
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 680
Points : 10 473
Points : 10 473
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Citation:
Envoyé par Lynecoln Voir le message
Les max que j'utilise c'est par rapport au post de punkoff ci-dessous. Sans les max, je suis obligé de mettre les noms de tous les champs dans le GROUP BY
Et pourtant ce serait mieux dans la mesure où dans cette requête-ci ce sont des dimensions :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  SELECT m.mbreID                    ,
         m.matricule                 ,
         m.nom                       ,
         m.prenoms                   ,
         c.catLibelle    AS categorie,
         q.quotamontant  AS quota    ,
         COUNT(t.mbreID) AS total  
    FROM tblmembres m
         INNER JOIN tblcategories c
           ON m.categorie = c.catID
         INNER JOIN tblquotas q
           ON q.catID = c.catID
         LEFT OUTER JOIN tblcotisations t
           ON t.mbreID = m.mbreID
GROUP BY m.mbreID      ,
         m.matricule   ,
         m.nom         ,
         m.prenoms     ,
         c.catLibelle  ,
         q.quotamontant;
__________________
Email : http://scr.im/waldar
Waldar 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 07h49.


 
 
 
 
Partenaires

Hébergement Web