GROUP BY
Логика:
- Сначала в таблице определяются строки, в которых в указанном в
GROUP BYстолбце есть одинаковые значения. - Далее по этим значениям записи объединяются в группы, причём в группе может быть даже одна запись.
- После этого с помощью агрегирующих функций над элементами этих групп, как правило, проводятся определённые операции. Например, с помощью
SUMвычисляется сумма значений в каком-либо столбце в каждой группе:
SELECT column_1, SUM(column_2) AS sum
FROM table
GROUP BY column_1
Уточнения:
- группировку можно делать сразу по нескольким колонкам:
SELECT column_1, column_2, SUM(column_3) AS sum
FROM table
GROUP BY column_1, column_2
- к группам, образовавшимся в результате
GROUP BY, можно применять сразу несколько агрегирующих функций (в том числе к разным колонкам):
SELECT column_1, SUM(column_2) AS sum, AVG(column_3) AS avg
FROM table
GROUP BY column_1
- агрегирующую функцию можно применить к той же самой колонке, по которой осуществляется группировка (Не всегда такая операция имеет смысл, но она допустима. Например, с помощью функции
COUNTможно посчитать количество записей, попавших в каждую группу.):
SELECT column_1, COUNT(column_1) AS count
FROM table
GROUP BY column_1
- после группировки к результатам агрегирующих функций можно применять другие функции. Также над ними можно сразу проводить арифметические операции
- агрегацию не обязательно проводить по уже имеющимся колонкам — можно сначала применить некоторую функцию в колонке из исходной таблицы, а затем сразу провести агрегацию по новой колонке:
SELECT column_1, SUM(some_function(column_2)) AS sum_over_function
FROM table
GROUP BY column_1
- группировку можно делать сразу по новым полям, посчитанным в
SELECT. При этом допускается использование вGROUP BYалиаса колонки, указанного вSELECT, но это синтаксический сахар в PostgreSQL, в других СУБД его может не быть, поэтому не рекомендуется так делать. Cледующие запросы дадут одинаковый результат:
SELECT DATE(column_1) AS date, SUM(column_2) AS sum
FROM table
GROUP BY DATE(column_1)
SELECT DATE(column_1) AS date, SUM(column_2) AS sum
FROM table
GROUP BY date
- делать агрегацию после группировки не обязательно. Если не указать агрегирующую функцию, то запрос вернёт уникальные значения в столбце (или уникальные комбинации значений в столбцах), т.е. тот же результат, что и оператор
DISTINCT(частый вопрос на собесах):
SELECT user_id
FROM user_actions
GROUP BY user_id
SELECT DISTINCT user_id
FROM user_actions
- при использовании группировки колонки, указанные в
SELECT, должны находиться и вGROUP BY, если они не используются в агрегирующих функциях. Это обязательное условие, и если оно не будет выполнено, то база данных вернёт ошибку. В обратную сторону указанное выше правило не работает: если мы что-то указали вGROUP BY, то это совсем не обязательно указывать вSELECT - группировка всегда выполняется после фильтрации, т.е. сначала выполняются инструкции в
WHEREи только потом данные группируются с помощьюGROUP BY - вместо названий колонок в блоке
GROUP BYможно использовать порядковые номера колонок, указанных вSELECT. Например, следующие запросы эквивалентны:
SELECT column_1, column_2, SUM(column_3) AS sum
FROM table
GROUP BY column_1, column_2
SELECT column_1, column_2, SUM(column_3) AS sum
FROM table
GROUP BY 1, 2
- При этом номера колонок из
SELECTможно также использовать при сортировке в оператореORDER BY:
SELECT column_1, column_2, SUM(column_3) AS sum
FROM table
GROUP BY 1, 2
ORDER BY 3