2011-01-27 15 views
5

Prendere le seguenti tabelle ...Posso includere una colonna non aggregata in una funzione di aggregazione in SQL senza inserirla in una clausola GROUP BY?

Classes 
ClassId ClassName 
1  Math 
2  Math 
3  Science 
4  Music 

Registrations 
RegistrationId ClassId StudentName 
1    1  Stu 
2    1  Rick 
3    2  John 
4    4  Barb 
5    4  Dan 
6    3  Einstein 

Sì, ci sono 2 classi con lo stesso nome (Math) in quanto potrebbero essere in tempi diversi. Mi piacerebbe avere una lista delle classi e il numero di studenti registrati per ognuno. Vorrei le seguenti colonne (ClassId, ClassName, StudentCount).

Il mio tentativo di questo sarebbe qualcosa sulla falsariga di ...

SELECT Classes.ClassId, Classes.ClassName, Count(Registrations.RegistrationId) 
FROM Classes 
INNER JOIN Registrations ON Classes.ClassId = Registrations.ClassId 
GROUP BY Classes.ClassId 

(Nota Vorrei groupby il classid ma NON ClassName). È possibile in SQLServer 2008? Ovviamente chiedo perché SQL si lamenta

"ClassName is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause." 

Grazie!

+0

È possibile selezionare solo l'ID e il conteggio aggregato in una sottoquery, quindi ricongiungersi alla tabella per i nomi. – Pointy

risposta

11

No, SQL Server non consente di omettere colonne da GROUP BY che non sono racchiuse in funzioni aggregate. Non c'è nulla di male nel incluso il nome della classe, perché il gruppo da verrà eseguita sulla combinazione del gruppo da colonne:

SELECT c.classid, 
     c.classname, 
     COUNT(r.registrationid) 
    FROM CLASSES c 
    JOIN REGISTRATIONS r ON r.classid = c.classid 
GROUP BY c.classid, c.classname 

Si potrebbe ricavare una tabella basata sul conteggio, utilizzando:

SELECT c.classid, 
     c.classname, 
     r.num 
    FROM CLASSES c 
    JOIN (SELECT t.classid, 
       COUNT(*) AS num 
      FROM REGISTRATIONS t 
     GROUP BY t.classid) r ON r.classid = c.classid 
2

è possibile mettere il ClassName nel gruppo dalla clausola, che sarà ok perché si tratta di un 1-to1 con il ClassID:

SELEZIONA Classes.ClassId, Classes.ClassName, conte (Registrations.RegistrationId) dalle classi INN ER JOIN Registrazioni ON Classes.ClassId = Registrations.ClassId GROUP BY Classes.ClassId, Classes.ClassName

o inserire un MAX (ClassName) nella clausola select. O uno produrrà lo stesso risultato.

5

Non ci dovrebbero essere problemi nell'includere Classes.ClassName nell'istruzione GROUP BY. Sarai raggruppato per le coppie distinte di ClassId e ClassName così (1, 'Math') e (2, 'Math') sono ancora due raggruppamenti distinti.

+0

@OMG Ponies e tutti gli altri ... grazie per avermi aiutato a capire che il gruppo funzionerà benissimo fintanto che manterrò entrambi (Classes.ClassId e Classes.ClassName). Sotto un momento di pura stupidità ho provato ad includere solo Classed.ClassName e non Classes.ClassId e ha raggruppato in modo indesiderato tutti i Math insieme. Vedo il mio errore e ringrazio tutti per avermi aiutato :) – Justin

1

No, non è possibile: è una contraddizione.

GROUP BY = collasso su valori discreti. Se non si collassa, è necessario aggregarlo.

In questo caso, si otterrebbe lo stesso risultato perché ClassName dipende da ClassID.

Problemi correlati