@Mr-Governor
Губернирую

Как работают агрегатные функции?

Например, есть таблица:

mysql> SELECT * FROM student;
+----+-----------+------+
| id | name | age |
+----+-----------+------+
| 1 | Дмитрий | 18 |
| 2 | Аркадий | 18 |
| 3 | Анастасия | 17 |
| 4 | NULL | NULL |
+----+-----------+------+

При использовании агрегатных функций получаем следующее:

mysql> SELECT id, name, age, COUNT(*) FROM student;
+----+---------+------+----------+
| id | name | age | COUNT(*) |
+----+---------+------+----------+
| 1 | Дмитрий | 18 | 4 |
+----+---------+------+----------+

Если count() подсчитывает каждую строку, почему результат не получился таким:

+----+-----------+------+----------+
| id | name | age | COUNT(*) |
+----+-----------+------+----------+
| 1 | Дмитрий | 18 | 1 |
| 2 | Аркадий | 18 | 2 |
| 3 | Анастасия | 17 | 3 |
| 4 | NULL | NULL | 4 |
+----+-----------+------+----------+

Как вообще работают агрегатные функции и чем они отличаются от обычных?
Объясните пожалуйста логику работы этих функций.
  • Вопрос задан
  • 1062 просмотра
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
В стандарте при использовании агрегатных функций каждое поле выборки, ORDER BY и HAVING должно быть либо результатом агрегатной функции, либо входить в GROUP BY. Таким образом приведённый вами запрос в стандарте недопустим.
MySQL, до последней версии, допускал нестандартное использование агрегирования, выбирая для неагрегированых полей первое попавшееся значение. Начиная с версии 5.7 MySQL начал требовать соблюдения стандарта, и приведённый вами запрос выдаст ошибку. Вернуться к старым настройкам можно отключив режим ONLY_FULL_GROUP_BY в настройках или явно используя агрегатную функцию ANY_VALUE() на полях, которые раньше не агрегировались. Ваш запрос в этом случае будет выглядеть как
SELECT ANY_VALUE(`id`), ANY_VALUE(`name`), ANY_VALUE(`age`), COUNT(*) 
  FROM `student`;

Поскольку в запросе не указано, по каким полям проводить группировку, MySQL группирует все строки в одну. Если использовать GROUP BY <список полей>, то будут группироваться строки с одинаковыми значениями указанных в списке полей. Так запрос
SELECT `age`, COUNT(*) 
  FROM `student`
  GROUP BY `age`;

выдаст
+------+----------+
| age  | COUNT(*) |
+------+----------+
|  18  |    2     |
|  17  |    1     |
| NULL |    1     |
+------+----------+
Ответ написан
Комментировать
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы