SmartQuery /ВОПРОС → ПРИМЕР → ПОНЯТНЫЙ ОТВЕТ
Базы данных

Как сгруппировать строки SQL по двум столбцам

Укажите оба столбца после GROUP BY: каждая уникальная пара значений станет одной группой. Агрегатная функция — например, SUM или AVG — вычислит результат внутри каждой такой группы.

Минимальный набор данных

Если каждая пара ключей встречается один раз, агрегат не объединяет несколько значений. Для наглядности возьмём продажи: две строки относятся к одной паре «регион / товар».

WITH sales(region, product, amount) AS (
    VALUES ('East', 'Book', 10),
           ('East', 'Book', 20),
           ('West', 'Book', 5)
)
SELECT region, product, SUM(amount) AS total
FROM sales
GROUP BY region, product
ORDER BY region, product;

Запрос использует CTE с VALUES и не создаёт постоянных таблиц. Пример рассчитан на PostgreSQL; синтаксис временного набора данных в другой СУБД может отличаться.

Результат группировки
regionproducttotal
EastBook30
WestBook5
Три продажи объединяются по region и product: East и Book — 10 плюс 20, всего 30; West и Book — 5
Группа определяется парой ключей, а сумма считается по её строкам.

Как выбрать ключи группировки

Сначала определите, что должна означать одна строка результата. Если нужен итог по региону независимо от товара, группируйте только по region. Если нужен итог по каждому товару в регионе, нужны оба ключа. Добавление уникального идентификатора продажи в GROUP BY снова разделит строки на отдельные группы.

WHERE и HAVING решают разные задачи

WHERE фильтрует исходные строки до группировки. HAVING фильтрует уже сформированные группы. Например, HAVING SUM(amount) > 10 оставит только группу East / Book с итогом 30.

SELECT region, product, SUM(amount) AS total
FROM sales
WHERE amount > 0
GROUP BY region, product
HAVING SUM(amount) > 10
ORDER BY total DESC, region, product;

Этот вариант предполагает существование таблицы sales либо такого же CTE перед SELECT. В результирующий SELECT обычно включают ключи группировки и агрегаты; неагрегированные выражения должны соответствовать правилам выбранной СУБД.

Что проверить перед использованием

  • Повторяются ли в тестовых данных комбинации ключей: иначе пример не покажет объединения строк.
  • Как обрабатываются NULL: COUNT(*) и COUNT(column) дают разные результаты при пустых значениях.
  • Нужен ли фиксированный порядок: GROUP BY сам по себе его не обещает, используйте ORDER BY.
  • Не появилась ли лишняя кратность после JOIN до группировки: она способна увеличить сумму.

Документация