К статье
Практический материал

Разработка и Конфигурация · 11 мин

Агрегатные функции в 1С: что это и как с ними работать

Что такое агрегатные функции в языке запросов 1С: СУММА, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ, КОЛИЧЕСТВО. Синтаксис, группировка, типичные ошибки и примеры.

Агрегатные функции в 1С — это специальные функции языка запросов, которые вычисляют одно итоговое значение по группе строк: сумму, среднее, минимум, максимум или количество записей. Они используются повсюду, где нужно получить сводные данные: обороты по контрагенту, остатки по складу, средний чек за период, количество документов.

Без агрегатных функций пришлось бы выгружать в память все строки и складывать их в цикле на встроенном языке — это медленно, особенно на больших таблицах, и усложняет код. Запрос с группировкой выполняет ту же работу на стороне СУБД за один проход по данным.

Агрегатные функции доступны в консоли запросов, в отчётах на СКД, в динамических списках и в любом программном запросе. Синтаксис един для всех типовых и самописных конфигураций, поэтому освоив их один раз, вы сможете применять их везде.

Какие агрегатные функции есть в языке запросов 1С

Встроенный язык запросов 1С поддерживает пять основных агрегатных функций. Каждая принимает в качестве аргумента поле или выражение и возвращает одно значение на группу строк.

ФункцияЧто вычисляетТипичное применение
СУММА(Поле)Сумма числовых значенийОбороты, выручка, количество товара
СРЕДНЕЕ(Поле)Среднее арифметическоеСредний чек, средняя цена закупки
МИНИМУМ(Поле)Минимальное значениеМинимальная цена, первая дата
МАКСИМУМ(Поле)Максимальное значениеПоследняя дата документа, максимальная скидка
КОЛИЧЕСТВО(Поле)Число строк со значениемКоличество документов, строк, записей

Отдельно стоит конструкция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) — она считает число уникальных значений. Например, сколько разных контрагентов фигурирует в продажах за месяц, а не сколько всего строк продаж.

Функции МИНИМУМ и МАКСИМУМ работают не только с числами, но и с датами и строками. Для дат минимум — самая ранняя дата, максимум — самая поздняя. Это удобный способ найти дату первого или последнего документа по условию.

Как работает группировка СГРУППИРОВАТЬ ПО

Агрегатная функция почти всегда используется вместе с конструкцией СГРУППИРОВАТЬ ПО. Она определяет, по каким полям строки объединяются в группы: запрос сначала раскладывает строки по «корзинам» с одинаковыми значениями группировочных полей, а затем для каждой корзины вычисляет агрегатные значения.

Главное правило: в списке выборки могут быть только поля из СГРУППИРОВАТЬ ПО и агрегатные функции. Если вы выбираете поле, которого нет в группировке и которое не обёрнуто в агрегатную функцию, конструктор запросов выдаст ошибку — платформа не знает, какое из значений группы вернуть.

Запрос.Текст =

"ВЫБРАТЬ

| Продажи.Контрагент КАК Контрагент,

| СУММА(Продажи.СуммаОборот) КАК СуммаПродаж

|ИЗ

| РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Контрагент";

Если агрегатные функции используются без СГРУППИРОВАТЬ ПО вообще, весь результат запроса считается одной группой — вы получите одну строку с общим итогом. Это нормальный приём, когда нужна, например, общая сумма продаж за период без разбивки.

Практические примеры запросов с агрегатными функциями

Рассмотрим типовые задачи, которые решаются агрегатными функциями. Все примеры можно проверить в консоли запросов на реальных данных вашей базы.

Сумма и количество по измерению

Классическая задача — обороты по контрагентам или номенклатуре. Группируем по нужному измерению и считаем СУММА и КОЛИЧЕСТВО:

ВЫБРАТЬ

Обороты.Номенклатура КАК Товар,

СУММА(Обороты.КоличествоОборот) КАК Продано,

СУММА(Обороты.СуммаОборот) КАК Выручка

ИЗ

РегистрНакопления.Продажи.Обороты(, , , ) КАК Обороты

СГРУППИРОВАТЬ ПО

Обороты.Номенклатура

Среднее значение и уникальные значения

Средний чек по клиенту считается как СРЕДНЕЕ по сумме документа, а число уникальных дней продаж — через КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...). Важно помнить: СРЕДНЕЕ усредняет по строкам выборки, а не по документам, поэтому для корректного среднего чека сначала сгруппируйте данные до уровня документа во вложенном запросе.

Минимум и максимум по датам

Чтобы найти первую и последнюю продажу по товару, примените МИНИМУМ и МАКСИМУМ к полю периода. Это быстрее и надёжнее, чем сортировка с ограничением количества строк, особенно когда результат нужен в разрезе множества товаров сразу.

Порядок построения запроса с итогами
  1. 1
    Откройте консоль запросов или конструктор запроса в конфигураторе
  2. 2
    Выберите таблицу-источник (например, виртуальную таблицу Обороты регистра накопления)
  3. 3
    Добавьте в выборку поле-измерение и оберните числовые поля в СУММА или другую функцию
  4. 4
    На закладке «Группировка» перенесите измерения в группировочные поля, агрегаты — в суммируемые
  5. 5
    Выполните запрос и сверьте итог с типовым отчётом по тому же регистру

Особенности функции КОЛИЧЕСТВО и значения NULL

Функция КОЛИЧЕСТВО имеет тонкое поведение: КОЛИЧЕСТВО(Поле) считает только строки, где поле не равно NULL, а КОЛИЧЕСТВО(*) считает все строки группы без исключений. При левых соединениях таблиц разница может быть существенной: если к справочнику присоединить таблицу продаж левым соединением, у товаров без продаж поле суммы будет NULL.

По той же причине СУММА по группе, где все значения NULL, вернёт NULL, а не ноль. Если дальше это значение участвует в вычислениях или выводится в отчёт, оберните его в ЕСТЬNULL(СУММА(Поле), 0) — иначе в отчёте появятся пустые ячейки, а арифметика с NULL даст NULL.

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) тоже игнорирует NULL. Если нужно посчитать уникальные ссылки, включая пустые, сначала замените NULL на явное значение через ЕСТЬNULL, а затем применяйте функцию.

Агрегатные функции в СКД и динамических списках

В отчётах на системе компоновки данных агрегатные функции работают на двух уровнях. Первый уровень — внутри запроса набора данных, как описано выше. Второй уровень — ресурсы СКД: на закладке «Ресурсы» для каждого показателя задаётся выражение агрегирования, например Сумма(Выручка), и СКД сама рассчитывает итоги по группировкам отчёта.

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

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

Типичные ошибки и как их проверить результат

Большинство проблем с агрегатными функциями связано не с синтаксисом, а с логикой группировки. Ниже — ошибки, которые встречаются чаще всего.

Типичные ошибки
01
Поле в выборке не входит в группировку и не обёрнуто в агрегатную функцию — запрос не выполняется с ошибкой группировки
02
Суммирование по таблице с лишней детализацией: соединение с табличной частью умножает строки, и СУММА задваивается или застраивается
03
СРЕДНЕЕ считается по строкам, а не по документам — средний чек получается заниженным при разном числе строк в документах
04
Забытый ЕСТЬNULL приводит к пустым итогам и NULL в последующих вычислениях
05
КОЛИЧЕСТВО вместо КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) завышает число уникальных объектов

Самая коварная ошибка — задвоение сумм из-за соединений. Если к документу присоединить таблицу, где на один документ приходится несколько строк, СУММА по полю документа умножится на число строк. Признак проблемы: итог запроса больше итога типового отчёта ровно в целое число раз. Лечение — сначала сгруппировать вложенный запрос до нужного уровня, потом соединять.

Проверять результат удобно сравнением с эталоном: типовым отчётом по тому же регистру за тот же период с теми же отборами. Совпадение общей суммы — необходимый, но не достаточный признак: дополнительно сверьте 2–3 строки в разрезе группировки, чтобы исключить взаимокомпенсирующие ошибки.

Контрольные точки

Как проверить результат

Общий итог запроса
Норма

Совпадает с итогом типового отчёта по регистру за тот же период

Тревожный признак

Итог больше или меньше — ищите задвоение соединений или лишний отбор

Строки без движений
Норма

Показывают 0 или отсутствуют осознанно

Тревожный признак

Пустые ячейки NULL там, где ожидался ноль

Число уникальных объектов
Норма

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Ссылка) совпадает с ручным подсчётом на малой выборке

Тревожный признак

Количество равно числу строк — забыто ключевое слово РАЗЛИЧНЫЕ

Когда агрегатные функции не нужны: альтернативы

Не каждую сводную задачу стоит решать группировкой в запросе. Если итоги нужны постоянно и по ним идут частые обращения (остатки товаров, взаиморасчёты), правильнее хранить их в регистре накопления — виртуальные таблицы Обороты и Остатки уже содержат заранее агрегированные данные, и запрос к ним работает быстрее, чем группировка сырой таблицы движений.

Для разовых вычислений по небольшой выборке в памяти допустим обход выборки в цикле с суммированием — например, когда параллельно с суммой нужна сложная построчная логика, которую в запросе не выразить. Но как только объём данных растёт, такой код становится узким местом по производительности.

Если нужны и детальные строки, и итоги одновременно, используйте конструкцию ИТОГИ ПО в запросе: выборка вернёт иерархический результат с итоговыми строками по указанным полям. Это удобно для вывода в дерево значений или табличный документ без повторного запроса.

Итог

Что важно запомнить

Агрегатные функции СУММА, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ и КОЛИЧЕСТВО сворачивают группы строк в одно значение и работают вместе с СГРУППИРОВАТЬ ПО. Следите за NULL и задвоением строк при соединениях, используйте ЕСТЬNULL и РАЗЛИЧНЫЕ, а результат сверяйте с типовым отчётом по регистру.

Частые вопросы об агрегатных функциях в 1С

Чем КОЛИЧЕСТВО(*) отличается от КОЛИЧЕСТВО(Поле)?

КОЛИЧЕСТВО(*) считает все строки группы, включая те, где конкретные поля равны NULL. КОЛИЧЕСТВО(Поле) считает только строки, где указанное поле имеет значение. При левых соединениях это даёт разные результаты, поэтому выбирайте вариант осознанно.

Почему СУММА вернула пустое значение вместо нуля?

СУММА по группе, где все значения NULL (типично при левом соединении без совпадений), возвращает NULL. Оберните выражение в ЕСТЬNULL(СУММА(Поле), 0), чтобы получить ноль и обезопасить дальнейшие вычисления.

Можно ли использовать агрегатные функции без СГРУППИРОВАТЬ ПО?

Да. Если группировка не задана, весь результат запроса трактуется как одна группа, и вы получите единственную строку с общим итогом. Это подходит для сводных показателей вроде общей выручки за период.

Как посчитать средний чек, если у документов разное число строк?

Сначала во вложенном запросе сгруппируйте данные до уровня документа (СУММА по каждому документу), а затем во внешнем запросе примените СРЕДНЕЕ к суммам документов. Иначе СРЕДНЕЕ усреднит строки, и документы с большим числом позиций получат больший вес.

Почему запрос с группировкой работает медленно?

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

Можно ли применять МИНИМУМ и МАКСИМУМ к датам и строкам?

Да. Для дат МИНИМУМ возвращает самую раннюю дату, МАКСИМУМ — самую позднюю, что удобно для поиска первого и последнего документа. Для строк сравнение идёт по алфавитному порядку, что редко бывает полезно, но технически работает.