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