Как в отчете СКД сложить строки и сгруппировать выручку по месяцам вместо дат

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Приветствуем вас, коллеги! Сегодня мы подробно разберем одну из классических задач, с которой регулярно сталкиваются как начинающие, так и опытные разработчики при создании отчетов на Системе компоновки данных (СКД) в 1С.

Представьте ситуацию: вам необходимо построить отчет по продажам, в котором отражается общая выручка по каждому менеджеру. Однако при выводе данных система компоновки упорно разбивает строки по каждой конкретной дате заказа или по документам-регистраторам. В итоге вместо красивой, лаконичной таблицы с ежемесячными итогами мы получаем огромную «простыню» детальных записей, которую крайне неудобно анализировать.

В рамках этой статьи мы подробно проанализируем, почему возникает такая проблема, почему простая попытка использовать конструкцию Регистратор.Дата приводит к ошибке «Поле не найдено "Регистратор.Дата"», и рассмотрим три профессиональных способа решения этой задачи: от настройки простых пользовательских полей до глубокой оптимизации запроса на уровне СУБД.

---

Выясняем причину: почему возникает ошибка «Поле не найдено "Регистратор.Дата"»?

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

Причина №1. Составной тип данных поля «Регистратор»

Поле Регистратор в виртуальных таблицах оборотов регистров накопления всегда имеет составной тип данных. Оно может ссылаться на десятки различных видов документов: «Реализация товаров и услуг», «Отчет комиссионера о продажах», «Акт выполненных работ» и так далее.

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

Причина №2. Различие в синтаксисе языка запросов и языка выражений СКД

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

НАЧАЛОПЕРИОДА(ЗаказКлиента.Дата, МЕСЯЦ)

А в языке выражений СКД (в том числе в пользовательских полях) параметр периодичности обязательно должен передаваться в виде строки в кавычках:

НАЧАЛОПЕРИОДА(ЗаказКлиентаДата, "Месяц")

Несоблюдение этого синтаксического правила также гарантированно приводит к ошибкам компиляции схемы компоновки данных.

---

Вариант решения №1. Использование пользовательского поля СКД (Быстрый способ)

Если вам нужно оперативно решить задачу прямо в режиме «1С:Предприятие» или в настройках схемы компоновки без изменения самого текста запроса, мы можем использовать механизм Пользовательских полей.

Поскольку в исходном запросе автора уже выбрано типизированное поле даты заказа — ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Дата КАК ЗаказКлиентаДата, нам вообще не нужно обращаться к проблемному полю Регистратор. Давайте настроим пользовательское поле по шагам:

  1. Откройте схему компоновки данных (вкладка «Настройки» в конфигураторе или настройки отчета в пользовательском режиме).
  2. Перейдите на вкладку «Пользовательские поля».
  3. Добавьте новое поле типа «Новое поле-выражение».
  4. Задайте для него понятное наименование, например: Месяц продажи.
  5. В поле «Выражение детальных записей» введите следующую формулу:
    НАЧАЛОПЕРИОДА(ЗаказКлиентаДата, "Месяц")
    Важно: обязательно используйте кавычки для указания периода "Месяц"!
  6. В поле «Выражение итогов» можно оставить пустое значение или продублировать выражение, если планируется рассчитывать итоги по этому полю.
  7. Перейдите в структуру настроек отчета и замените старую группировку по детальной дате или заказу на наше новое поле Месяц продажи.

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

---

Вариант решения №2. Группировка данных на уровне запроса (Производительный способ)

Использование пользовательских полей СКД — отличный вариант для быстрой кастомизации, но с точки зрения производительности правильнее готовить данные заранее, еще на этапе выполнения запроса к базе данных. Это избавит СКД от необходимости производить дополнительные вычисления на стороне сервера приложений 1С.

Давайте проанализируем исходный запрос автора темы:


ВЫБРАТЬ
    ВыручкаИСебестоимостьПродажОбороты.Менеджер КАК Менеджер,
    СУММА(ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиОборот) КАК СуммаВыручкиОборот,
    ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Ссылка КАК ЗаказКлиентаСсылка,
    ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Дата КАК ЗаказКлиентаДата,
    ВыручкаИСебестоимостьПродажОбороты.Регистратор КАК Регистратор
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Менеджер.Подразделение = &Подразделение) КАК ВыручкаИСебестоимостьПродажОбороты
СГРУППИРОВАТЬ ПО
    ВыручкаИСебестоимостьПродажОбороты.Менеджер,
    ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Ссылка,
    ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Дата,
    ВыручкаИСебестоимостьПродажОбороты.Регистратор

Чтобы сгруппировать данные по месяцам непосредственно в СУБД, мы преобразуем этот запрос следующим образом. Мы исключим детальные поля заказа и регистратора (если они действительно не требуются для раскрытия информации в отчете) и добавим поле с началом периода месяца:


ВЫБРАТЬ
    ВыручкаИСебестоимостьПродажОбороты.Менеджер КАК Менеджер,
    НАЧАЛОПЕРИОДА(ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Дата, МЕСЯЦ) КАК ПериодМесяц,
    СУММА(ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиОборот) КАК СуммаВыручкиОборот
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Менеджер.Подразделение = &Подразделение) КАК ВыручкаИСебестоимостьПродажОбороты
СГРУППИРОВАТЬ ПО
    ВыручкаИСебестоимостьПродажОбороты.Менеджер,
    НАЧАЛОПЕРИОДА(ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента.Дата, МЕСЯЦ)

Преимущества данного подхода:

---

Вариант решения №3. Настройка периодичности виртуальной таблицы (Архитектурно верный способ)

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

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

Давайте изменим параметры виртуальной таблицы и оптимизируем логику:

  1. Откроем конструктор запроса.
  2. Для таблицы ВыручкаИСебестоимостьПродаж.Обороты заменим параметр периодичности с Регистратор на «Месяц».
  3. После этого в списке доступных полей нашей таблицы появится стандартное предопределенное поле «Период», которое автоматически будет содержать дату начала соответствующего месяца.

Посмотрим на финальный, максимально оптимизированный текст запроса:


ВЫБРАТЬ
    ВыручкаИСебестоимостьПродажОбороты.Менеджер КАК Менеджер,
    ВыручкаИСебестоимостьПродажОбороты.Период КАК ПериодМесяц,
    ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиОборот КАК СуммаВыручкиОборот
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, Месяц, Менеджер.Подразделение = &Подразделение) КАК ВыручкаИСебестоимостьПродажОбороты

Почему этот вариант самый лучший?

---

Резюме и рекомендации

Мы проанализировали проблему детального вывода строк в СКД и нашли три пути её решения. Подведем итог, какой инструмент выбрать в зависимости от ваших задач:

← На главную