2011-06-30 5 views
7

J'ai essayé de refaire cette déclaration mais en vain.SQL SUM et CASE et DISTINCT

SELECT b.Program AS Program, 
    SUM(CASE WHEN a.Gender LIKE 'M%' THEN 1 ELSE NULL END) AS Males,  
    SUM(CASE WHEN a.Gender LIKE 'F%' THEN 1 ELSE NULL END) AS Females, 
    SUM(CASE WHEN e.Activity LIKE 'Arts' THEN 1 ELSE NULL END) AS Arts, 
    AVG(CASE WHEN a.Gender LIKE 'M%' THEN CAST(f.Score AS DEC(10,2)) ELSE NULL END) 
AS MalesAverage 
FROM tblChildren a 
    LEFT JOIN tblInvolvement b ON b.ChildID = a.ChildID 
    LEFT JOIN tblActivities e ON e.ChildID = b.ChildID 
    LEFT JOIN tblScores f ON f.ChildID = b.ChildID 
WHERE b.Place = 'Location' 
    AND b.Program = 'Program' 
    AND b.Year = '2009-10' 
    AND f.Assessment LIKE '%Pre%Assessment%' 
    AND e.StudentID = b.StudentID 
GROUP BY Program 

Maintenant, je vais obtenir des résultats comme:

Program Males Females Arts MalesAverage 
--------------------------------------- 
Program 7  5  1 50.000000 

Le problème est qu'il n'y a que 4 mâles et 3 femelles, et que quand j'ajoute les tblActivites, il semble donner des doublons. Après avoir regardé à travers j'ai remarqué qu'il y avait 12 ChildID dans la table des Activités, la raison étant que les enfants étaient liés à plus d'une activité. J'ai essayé d'utiliser quelque chose comme:

SELECT SUM(DISTINCT CASE WHEN a.Gender LIKE 'M%' THEN 1 ELSE NULL END) AS Males 

Cependant, il a juste retourné 1 sous la colonne des mâles. Toute aide serait appréciée. Et juste pour clarifier plus loin, les tables sont clavées ensemble par le ChildID, j'ai juste besoin d'aide m'assurant que je retourne la bonne information. Si cela est résolu, alors ma liste massive de ces choses sera résolue. Éviter GROUP BY pour tout est préférable vu que j'ai beaucoup de données.

+0

@niktrs Comme expliqué dans la réponse ci-dessous qui donne encore 7 mâles, quand les résultats appropriés devraient être 4. – jnewkirk

+0

vérifier les relations entre la table et les jointures. Exécutez la requête sans les agrégats et vérifiez le résultat pour quelque chose d'étrange. – niktrs

Répondre

11

Est-ce que cela fonctionnerait?

COUNT(DISTINCT CASE WHEN a.Gender LIKE 'M%' THEN a.ChildID ELSE NULL END) AS Males 

Je soupçonne qu'il ya de meilleures façons de faire la jonction dans l'ensemble, mais sans savoir beaucoup plus sur le schéma que je ne sais vraiment pas.

+0

Qu'avez-vous besoin de savoir exactement? Je peux donner des noms plus génériques que ce que j'ai réellement vu car ce sont déjà des noms de tables génériques et non réels. – jnewkirk

+0

Je commencerais par, quelles sont les clés primaires de ces tables? Mais je pense que l'expression COUNT que j'ai donnée répondra à votre problème immédiat. –

+0

Cela fonctionne mais je pourrais aussi avoir besoin de quelques précisions pour la fonction d'agrégat AVG mais j'apprécie beaucoup votre aide. – jnewkirk

0

Vous ne montrez pas les données de base, mais je suis prêt à parier que vous avez plusieurs lignes par personne et par programme.

Vous GROUP BY Program qui agrège par programme, mais si par exemple John Smith a deux lignes avec cet ID de programme, il se compté comme MALE deux fois. S'il vous plaît nous montrer votre structure de table afin que nous puissions vous donner une question plus claire. Idéalement, vous obtiendrez le compte à partir d'une sous-sélection en utilisant un GROUP BY sur quelque chose comme Person_ID de sorte que vous n'obtenez pas de comptes en double.

+0

C'est ce que j'essayais d'éviter. Le programme n'est pas le problème cependant. "Après avoir regardé à travers j'ai remarqué qu'il y avait 12 ChildID dans la table des Activités, la raison étant que ces enfants étaient liés à plus d'une activité". Comme je l'ai dit, c'est le problème, l'enfant est lié à plus d'une activité à la fois produisant des ChildID identiques dans le tblActivities qui a 2 colonnes. ChildID et Activité. Je voudrais cependant éviter le GROUP BY, mais si c'est inévitable, je suppose que je peux le faire. – jnewkirk