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