При разработке отчетов на базе системы компоновки данных (СКД) начинающие разработчики нередко сталкиваются с ситуацией, когда одни и те же документы-регистраторы выводятся в отчете по несколько раз либо некорректно рассчитываются итоговые остатки денежных средств. Разберем типичные ошибки при составлении запросов к регистрам накопления, выясним причины дублирования строк и рассмотрим правильный алгоритм построения отчета.
Проанализируем исходный запрос, в котором была допущена ошибка. Разработчик попытался объединить выборку из физической таблицы движений регистра с выборкой из виртуальной таблицы остатков и оборотов:
ВЫБРАТЬ
ДенежныеСредстваНаличные.Регистратор КАК Регистратор,
ДенежныеСредстваНаличные.Период КАК Период,
ДенежныеСредстваНаличные.Касса,
NULL КАК СуммаНачальныйОстаток,
NULL КАК СуммаКонечныйОстаток,
NULL КАК СуммаПриход,
NULL КАК СуммаРасход
ИЗ
РегистрНакопления.ДенежныеСредстваНаличные КАК ДенежныеСредстваНаличные
ГДЕ
ДенежныеСредстваНаличные.Период МЕЖДУ &НачалоПериода И &КонецПериода
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДенежныеСредстваНаличныеОстаткиИОбороты.Регистратор,
ДенежныеСредстваНаличныеОстаткиИОбороты.ПериодСекунда,
ДенежныеСредстваНаличныеОстаткиИОбороты.Касса,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаНачальныйОстаток,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаКонечныйОстаток,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаПриход,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаРасход
ИЗ
РегистрНакопления.ДенежныеСредстваНаличные.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК ДенежныеСредстваНаличныеОстаткиИОбороты
Выясним, почему такой подход приводит к дублированию строк и неверным итогам:
РегистрНакопления.ДенежныеСредстваНаличные содержит список всех совершенных записей (движений). Виртуальная таблица ОстаткиИОбороты формируется платформой 1С на основе тех же самых движений и итогов регистра. Выполняя оператор ОБЪЕДИНИТЬ ВСЕ, мы принудительно выводим сначала строки из физической таблицы, а затем те же самые движения и остатки из виртуальной таблицы. В результате каждый регистратор дублируется.ОстаткиИОбороты уже содержит в себе всю необходимую информацию: измерение (касса), документ движения (регистратор), период и числовые ресурсы.Чтобы получить отчет с детализацией по кассам, документам-регистраторам, датам, а также с корректными начальными остатками, оборотами (приход/расход) и конечными остатками, достаточно одного простого обращения к виртуальной таблице ОстаткиИОбороты без каких-либо объединений и соединений.
Посмотрим на корректный текст запроса:
ВЫБРАТЬ
ДенежныеСредстваНаличныеОстаткиИОбороты.Касса КАК Касса,
ДенежныеСредстваНаличныеОстаткиИОбороты.ПериодСекунда КАК ПериодСекунда,
ДенежныеСредстваНаличныеОстаткиИОбороты.Регистратор КАК Регистратор,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаНачальныйОстаток КАК СуммаНачальныйОстаток,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаПриход КАК СуммаПриход,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаРасход КАК СуммаРасход,
ДенежныеСредстваНаличныеОстаткиИОбороты.СуммаКонечныйОстаток КАК СуммаКонечныйОстаток
ИЗ
РегистрНакопления.ДенежныеСредстваНаличные.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
Авто,
ДвиженияИГраницыПериода,
) КАК ДенежныеСредстваНаличныеОстаткиИОбороты
Разберем параметры виртуальной таблицы, которые мы использовали:
Авто. Позволяет СКД автоматически определять необходимую периодичность на основе полей, выбранных в группировках отчета. При выборе поля Регистратор платформа детализирует данные до конкретного документа.ДвиженияИГраницыПериода. Обеспечивает получение корректных входящих и исходящих остатков на границы заданного периода отчета, даже если по кассе не было движений в течение выбранного интервала.Даже при правильном тексте запроса в СКД могут возникать визуальные задвоения или завышение итоговых сумм, если не настроены роли полей и ресурсы. Разберем по шагам, как настроить схему компоновки данных:
Для полей СуммаНачальныйОстаток и СуммаКонечныйОстаток необходимо указать соответствующие роли. В колонке «Роль» для начального остатка задается признак Начальный остаток, имя группы — например, Сумма. Для конечного остатка указывается признак Конечный остаток с тем же именем группы Сумма.
Если в группировках выводятся и дата, и документ, для поля ПериодСекунда в роли указывается Период = 1, а для поля Регистратор — Период = 2 с типом Дополнительный и указанием родительского периода ПериодСекунда. Это исключает избыточные дублирующие строки при группировке.
Обороты (СуммаПриход, СуммаРасход) рассчитываются через стандартную агрегатную функцию: Сумма(СуммаПриход). Для полей начального и конечного остатков при правильно назначенных ролях платформа рассчитывает остаток по правилам остатков (на начало первой точки периода и конец последней), предотвращая простое суммирование остатков по всем строкам регистратора.
Рассмотрим дополнительные рекомендации, которые помогут избежать проблем при работе с отчетами по денежным средствам:
ОстаткиИОбороты(..., ..., ..., ..., Касса = &Касса), а не в условие ГДЕ. Это существенно снижает нагрузку на СУБД, так как расчет остатков выполняется только по нужной аналитике.ОстаткиИОбороты возвращает данные исключительно по проведенным документам, сформировавшим движения. Если стоит задача найти первичные документы, по которым движения еще не сделаны (например, пробитые чеки без оформленного ПКО), обращаться только к регистру недостаточно — в этом случае потребуется левое соединение таблицы документов с таблицей регистра.