Агрегирование и группировка

Как быть, если надо посчитать общее количество строк таблицы или найти запись, содержащую максимальное значение, или посчитать сумму значений столбца? Для этих целей в языке SQL предусмотрены различные функции агрегирования данных. Наиболее используемые – count(), sum(), avr(), min(), max(). Используют их совместно с оператором SELECT.

Вывод количества столбцов таблицы:

sqlite> SELECT count() FROM pages;

Поиск максимального ID:

sqlite> SELECT max(_id) FROM pages;

Количество различных вариантов значения столбца:

sqlite> SELECT count(DISTINCT theme) FROM pages;

Использование функций агрегирования в SQL

На скрине команда с DISTINCT возвращает 3 потому, что у нас встречается три разных значения в столбце theme – это значения 1, 2 и 3. Тема 1 встречается у двух записей, но благодаря агрегированию они учитываются как одна.

Вообще DISTINCT перед именем столбца выводит его различающиеся значения. Например, мы хотим узнать, какие темы используются в таблице pages:

sqlite> SELECT DISTINCT theme FROM pages;
1
2
3

Если в функцию count() передается просто имя столбца, например count(theme), то она возвращает количество записей с не NULL значениями. Если в указанном столбце нигде не встречается NULL, то результат будет совпадать с общим количеством записей.

Передача аргументов в функцию count()

Перед агрегированием можно выполнить фильтрацию. Данная команда посчитает количество страниц определенной темы:

sqlite> SELECT count() FROM pages WHERE theme = 1;
2

Обратим внимание, в SQL сначала выполняется фильтрация, то есть оператор WHERE. И только после этого агрегирование, то есть функция count(). Таким образом, из всей таблицы сначала фильтруются записи с темой 1. После этого считается их количество.

Если было бы наоборот, то приведенная выше команда не сработала, потому что функция count() вернула бы число-количество строк таблицы, и фильтровать из него было бы уже нечего.

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

sqlite> SELECT theme FROM pages GROUP BY theme;
1
2
3

Таким образом мы можем узнать, на какие темы имеются страницы в базе данных.

Часто группировка и агрегирование фигурируют в одной команде. Например, надо выяснить количество записей в каждой группе:

sqlite> SELECT theme,count() FROM pages GROUP BY theme;

Здесь будут выведены два столбца. В первом будет номер темы, во втором – количество страниц темы. Функция count() будет выполняться после группировки по темам. Она будет считать количество записей в каждой теме.

Примеры группировки и агрегирования в SQLite

На скрине в последней команде используется переименование столбца count() в столбец num. Делается это с помощью ключевого слова AS.

Пример совместного использования группировки и функции max():

sqlite> SELECT theme, max(num) FROM pages GROUP BY theme;
theme       max(num)  
----------  ----------
1           10        
2           100       
3           100 

Здесь сначала происходит группировка записей по темам. Потом в каждой группе ищется запись с максимальным значением столбца num.

Для вывода можно указывается столбец таблицы, группировка по которому не выполняется:

sqlite> SELECT title,theme,max(num) FROM pages GROUP BY theme;
Amount of Information|1|10
Binary System|2|100
Boolean Lows|3|100

В примере выше это поле title. Однако подобное не всегда уместно:

sqlite> SELECT title, theme, count() FROM pages GROUP BY theme;
What is Information|1|2
Binary System|2|1
Boolean Lows|3|1

У нас две страницы первой темы, но поскольку мы выводим в одной строке целую группу, название другой страницы первой темы не показано. Таким образом, хотя можно указывать столбцы по которым группировка не выполняется, иногда в этом нет смысла.