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