Можно ли включить неагрегированный столбец в статистическую функцию в SQL, не помещая его в предложение GROUP BY? - PullRequest
5 голосов
/ 27 января 2011

Возьмите следующие таблицы ...

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

Да, есть 2 класса с одинаковым именем (Math), которые могут быть в разное время. Я хотел бы получить список классов и количество студентов, зарегистрированных для каждого. Я хотел бы следующие столбцы (ClassId, ClassName, StudentCount).

Моя попытка сделать это была бы чем-то вроде ...

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

(Обратите внимание, я хотел бы, чтобы GroupBy был ClassId, но НЕ ClassName). Возможно ли это в SQLServer 2008? Очевидно, я спрашиваю, потому что SQL жалуется

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

Спасибо!

Ответы [ 4 ]

11 голосов
/ 27 января 2011

Нет, SQL Server не позволяет опускать столбцы из GROUP BY, которые не включены в агрегатные функции. Включение имени класса не повредит, поскольку группировка по будет выполняться при комбинировании группы по столбцам:

  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

Вы можете получить таблицу на основе подсчета, используя:

  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
5 голосов
/ 28 января 2011

Не должно быть никакого вреда, если вы включите Classes.ClassName в ваш оператор GROUP BY.Вы будете группировать по разным парам ClassId и ClassName, поэтому (1, 'Math') и (2, 'Math') по-прежнему являются двумя разными группами.

2 голосов
/ 28 января 2011

Вы можете поместить ClassName в предложение group by, что будет хорошо, потому что это 1-to1 с ClassID:

SELECT Classes.ClassId, Classes.ClassName, Count (Registrations.RegistrationId) ОТ классов ВНУТРЕННИЕ СОЕДИНЕНИЯ Регистрация на Classes.ClassId = Registrations.ClassId GROUP BY Classes.ClassId, Classes.ClassName

или введите MAX (ClassName) в предложении select. Любой из них даст тот же результат.

1 голос
/ 28 января 2011

Нет, вы не можете: это противоречие.

GROUP BY = свернуть в дискретные значения. Если вы не свернетесь, вам нужно объединить его.

Как это бывает, вы все равно получите тот же результат, потому что ClassName зависит от ClassID.

...