MySQL / 7. Формирование итогов

Управление порядком вывода итоговой информации

Задача
Вы хотите упорядочить результат запроса, выводящего итоговую информацию.

Решение
Если желаемый порядок недостижим при помощи инструкции GROUP BY, используйте инструкцию ORDER BY.

Обсуждение
В MySQL GROUP BY не только группирует, но и сортирует. Поэтому часто нет необходимости дополнительно использовать инструкцию ORDER BY в запросе, выводящем итоговую информацию. Если же вы хотите изменить порядок, задаваемый инструкцией GROUP BY по умолчанию, используйте ORDER BY. Например, чтобы вычислить количество дней за рулем и общее количество миль для каждого водителя из таблицы driver_log, выполним такой запрос:

mysql> SELECT name, COUNT(*) AS days, SUM(miles) AS mileage
-> FROM driver_log GROUP BY name;

+-------+------+-------------+
| name  | days | total miles |
+-------+------+-------------+
| Ben     | 3      | 362           |
| Henry | 5       | 911          |
| Suzi    | 2       | 893          |
+-------+------+-------------+

Результат упорядочен по именам. Если же вы хотите выводить водителей в порядке убывания проделанных миль или количества рабочих дней, добавьте в запрос соответствующую инструкцию ORDER BY:

mysql> SELECT name, COUNT(*) AS days, SUM(miles) AS mileage
-> FROM driver_log GROUP BY name
-> ORDER BY days DESC;

+-------+------+---------+
| name  | days | mileage |
+-------+------+---------+
| Henry | 5      | 911        |
| Ben     | 3      | 362        |
| Suzi     | 2      | 893       |
+-------+------+---------+

mysql> SELECT name, COUNT(*) AS days, SUM(miles) AS mileage
-> FROM driver_log GROUP BY name
-> ORDER BY mileage DESC;

+-------+------+---------+
| name  | days | mileage |
+-------+------+---------+
| Henry | 5      | 911       |
| Suzi     | 2     | 893       |
| Ben     | 3     | 362       |
+-------+------+---------+

Для ссылки в инструкции ORDER BY на итоговое значение необходимо использовать псевдоним или позицию столбца в списке вывода. Это касается даже версий MySQL 3.23.2 и выше, которые обычно разрешают применять выражения в инструкции ORDER BY; но эти выражения должны ссылаться на индивидуальные значения, а не на вычисленные.

Иногда можно изменить порядок вывода итоговой информации, не прибегая к инструкции ORDER BY, за счет выбора подходящего выражения для инструкции GROUP BY. Например, если вы хотите узнать, сколько штатов вступило в Союз в каждый из дней недели, и группируете результаты по названию дня недели, то они будут выведены в лексическом порядке:

mysql> SELECT DAYNAME(statehood), COUNT(*) FROM states
-> GROUP BY DAYNAME(statehood);

+--------------------------+-------------+
| DAYNAME(statehood) | COUNT(*) |
+--------------------------+-------------+
| Friday                          | 8               |
| Monday                       | 9               |
| Saturday                     | 11             |
| Thursday                     | 5              |
| Tuesday                       | 6              |
| Wednesday                 | 11            |
+--------------------------+------------+

Из списка, конечно, можно извлечь информацию о том, что ни один из штатов не вступил в Союз в воскресенье, но для этого требуется провести некоторый анализ результата. Вывод был бы более понятным, если бы применялось упорядочивание по дням недели. Можно добавить инструкцию ORDER BY для сортировки по числовому значению дня недели, но есть и другой способ достижения того же результата, причем без помощи ORDER BY: выполним группировку по DAYOFWEEK(), а не по DAYNAME():

mysql> SELECT DAYNAME(statehood), COUNT(*)
-> FROM states GROUP BY DAYOFWEEK(statehood);

+--------------------------+-------------+
| DAYNAME(statehood) | COUNT(*) |
+--------------------------+-------------+
| Monday                       | 9               |
| Tuesday                       | 6               |
| Wednesday                 | 11             |
| Thursday                     | 5               |
| Friday                          | 8               |
| Saturday                     | 11              |
+--------------------------+-------------+

Статьи по MySQL на эту тему:

Итоги по датам
Нахождение наибольшего и наименьшего из итоговых значений
Одновременная работа с итогами по группам и общим итогом
Формирование отчета, содержащего итоговую информацию и список

Вернуться в раздел: MySQL / 7. Формирование итогов