2011-01-27 10 views
5

tomar las siguientes tablas ...¿Puedo incluir una columna no agregada en una función agregada en SQL sin ponerla en una cláusula 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í, hay 2 clases con el mismo nombre (Matemáticas), ya que pueden estar en diferentes momentos. Me gustaría obtener una lista de las clases y el número de estudiantes registrados para cada una. Me gustaría las siguientes columnas (ClassId, ClassName, StudentCount).

Mi intento de esto sería algo en la línea de ...

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

(Nota quisiera GroupBy la ClassId pero NO NombredeClase). ¿Es esto posible en SQLServer 2008? Obviamente me pregunto porque SQL se queja

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

Gracias!

+0

Puede seleccionar solo el ID y el conteo agregado en una subconsulta, y luego volver a unirse a la tabla para los nombres. – Pointy

Respuesta

11

No, SQL Server no le permite omitir columnas de GROUP BY que no están envueltas en funciones agregadas. No hay daño en la inclusión del nombre de la clase, ya que el grupo de se llevará a cabo en la combinación del grupo de columnas:

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 

Usted podría derivar una tabla basada en el recuento, usando:

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

Usted puede poner el nombre de clase en la cláusula GROUP BY, que será bien porque está a 1 a 1 con el ClassID:

SELECT Classes.ClassId, Classes.ClassName, Count (Registrations.RegistrationId) de las clases INN ER JOIN Registros EN Classes.ClassId = Registrations.ClassId GROUP BY Classes.ClassId, Classes.ClassName

o poner un MAX (NombreClase) en la cláusula SELECT. Cualquiera de los dos dará el mismo resultado.

5

No debe haber ningún daño al incluir Classes.ClassName en su instrucción GROUP BY. Usted estaría agrupando por los distintos pares de ClassId y ClassName de modo que (1, 'Matemáticas') y (2, 'Matemáticas') siguen siendo dos agrupaciones distintas.

+0

@OMG Ponies y todos los demás ... gracias por ayudarme a darme cuenta de que el grupo funcionará bien siempre y cuando conserve ambos (Classes.ClassId y Classes.ClassName). En un momento de pura estupidez intenté incluir solo Classed.ClassName y no Classes.ClassId y agrupaba indeseablemente todas las matemáticas juntas. Veo mi error y gracias a todos por ayudarme :) – Justin

1

No, no puedes: es una contradicción.

GROUP BY = colapsar a valores discretos. Si no colapsas, debes agregarlo.

Como sea, obtendría el mismo resultado de todos modos porque ClassName depende de ClassID.

Cuestiones relacionadas