Как сгруппировать данные в отчете 1С по дням?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

Использование функции НАЧАЛОПЕРИОДА в запросе

Самый эффективный и распространенный способ "отсечь" время в запросе — это использование встроенной функции НАЧАЛОПЕРИОДА. Разберем по шагам, как это работает. Когда мы обращаемся к реквизиту Дата, СУБД возвращает полное значение. Функция НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) приводит любую дату к началу соответствующих суток (00:00:00).

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


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

В этом примере мы создали новое поле ПериодДень. Важно помнить: если вы используете группировку СГРУППИРОВАТЬ ПО, то выражение в поле выбора и в секции группировки должно быть идентичным. В противном случае запрос выдаст ошибку синтаксиса.

Отличие НАЧАЛОПЕРИОДА от функции ДЕНЬ

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

Если вы примените функцию ДЕНЬ, то данные за 1-е января и 1-е февраля сольются в одну группу "1", так как число месяца у них одинаковое. Поэтому для разделения данных по конкретным календарным датам всегда используйте НАЧАЛОПЕРИОДА.

Особенности работы в Системе компоновки данных (СКД)

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

Разберем, как это настроить в конфигураторе:

  1. Перейдите на закладку "Наборы данных".
  2. Найдите ваше поле Дата.
  3. В колонке "Роль" нажмите на кнопку редактирования. Там можно указать, что это поле является периодом, и задать тип периода (День, Неделя, Месяц и т.д.).
  4. Также можно использовать "Выражение представления". Например, чтобы вместо полной даты пользователь видел только день, укажите: Формат(Дата, "ДФ=dd.MM.yyyy").

Другой вариант в СКД — использование системных полей. Если ваше поле имеет тип Дата, СКД автоматически предлагает виртуальные подполя, такие как Дата.Час, Дата.День, Дата.Месяц. Вы можете просто выбрать Дата.НачалоДня в настройках группировки отчета без написания лишнего кода в запросе.

Форматирование вывода в табличном документе

После того как мы сгруппировали данные, в ячейках отчета все равно может отображаться время "00:00:00". Чтобы отчет выглядел профессионально, необходимо настроить формат вывода. В 1С это делается через строку формата.

Рассмотрим пример установки формата программно при выводе в ТабличныйДокумент:


ОбластьМакета = Макет.ПолучитьОбласть("Строка");
ОбластьМакета.Параметры.ДатаПоля = Формат(Выборка.ПериодДень, "ДФ=dd.MM.yyyy");
ТабДок.Вывести(ОбластьМакета);

В строке формата "ДФ=dd.MM.yyyy":

Проблема "пустых дней"

Проанализируем ситуацию: вам нужно вывести отчет за месяц, но в некоторые дни продаж не было. Обычный запрос просто пропустит эти даты, и в отчете возникнет "дырка".

Чтобы вывести все дни месяца, включая пустые, мы рекомендуем два подхода:

  1. В СКД: В настройках группировки по периоду установите свойство "Дополнение периода". Укажите дату начала и дату окончания. Система сама "дорисует" недостающие дни с нулевыми показателями.
  2. В запросе: Используйте левое соединение с производственным календарем или временной таблицей, содержащей все даты периода.

Оптимизация и производительность

Группировка по выражению НАЧАЛОПЕРИОДА выполняется на стороне сервера СУБД. Это достаточно быстрая операция, но при работе с миллионами записей стоит учитывать следующие моменты:

Во-первых, всегда ограничивайте выборку в секции ГДЕ по индексированным полям (каким является стандартное поле Дата в документах). Во-вторых, если вы работаете с регистрами, используйте виртуальные таблицы (например, Обороты), передавая в параметры периодичность ДЕНЬ. Это работает значительно быстрее, чем запрос к основной таблице регистра с последующей группировкой.


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

В данном случае система сама подготовит данные, уже сгруппированные по дням, что является наиболее "правильным" способом с точки зрения архитектуры 1С.

← На главную